Files
geg-gas-pcitc/xjrsoft-auth/src/main/java/com/xjrsoft/auth/controller/LoginController.java
2025-02-08 17:51:37 +08:00

264 lines
11 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.xjrsoft.auth.controller;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.xjrsoft.auth.dto.LoginDto;
import com.xjrsoft.auth.service.ILoginService;
import com.xjrsoft.auth.service.SsoService;
import com.xjrsoft.common.core.annotation.XjrLog;
import com.xjrsoft.common.core.config.KeyCloakConfig;
import com.xjrsoft.common.core.config.XjrSmsConfig;
import com.xjrsoft.common.core.constant.GlobalConstant;
import com.xjrsoft.common.core.domain.result.R;
import com.xjrsoft.common.core.enums.EnabledMark;
import com.xjrsoft.common.core.enums.YesOrNoEnum;
import com.xjrsoft.common.core.exception.MyException;
import com.xjrsoft.common.core.uitls.SmsSender;
import com.xjrsoft.common.redis.service.RedisUtil;
import com.xjrsoft.organization.client.IOauthClient;
import com.xjrsoft.organization.client.IUserClient;
import com.xjrsoft.organization.entity.User;
import com.xjrsoft.system.client.ILoginConfigClient;
import com.xjrsoft.system.dto.*;
import com.xjrsoft.system.entity.LoginConfig;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.keycloak.authorization.client.AuthzClient;
import org.keycloak.authorization.client.Configuration;
import org.keycloak.representations.AccessTokenResponse;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author: tzx
* @Date: 2023/10/12 15:39
*/
@RestController
@Tag(name = "登录模块")
@RequestMapping(GlobalConstant.SYSTEM_MODULE_PREFIX)
@RequiredArgsConstructor
public class LoginController {
private final ILoginService loginService;
private final IUserClient userClient;
private final RedisUtil redisUtil;
private KeyCloakConfig keyCloakConfig;
private SmsSender smsSender;
private XjrSmsConfig smsConfig;
private IOauthClient oauthClient;
private final ILoginConfigClient loginConfigClient;
private SsoService ssoService;
@PostMapping(value = {"/login/{ltpasToken}", "/login"})
@Operation(summary = "登录", description = "传入账号:account,密码:password")
@XjrLog(value = "账号密码登录成功")
public R login(@RequestBody @Valid LoginDto dto, @PathVariable(required = false) String ltpasToken) {
if(StrUtil.isNotBlank (ltpasToken)) {
String userName = ssoService.auth(ltpasToken);
if(StrUtil.isNotBlank(userName)) {
dto.setUserName(userName);
User user = loginService.getUserInfoByName(userName);
dto.setPassword(user.getPassword());
return R.ok(loginService.login(dto));
} else {
return R.error("秘钥登录失败");
}
}
return R.ok(loginService.login(dto));
}
@PostMapping("/create-token")
@Operation(summary = "创建token", description = "传入账号:account,密码:password")
@XjrLog(value = "账号密码登录成功")
public R createToken(@RequestBody @Valid CreateTokenDto dto) {
return R.ok(loginService.createToken(dto));
}
/**
* 发送验证码
*/
@GetMapping("/captcha")
@XjrLog(value = "发送验证码")
@Operation(summary = "发送验证码", description = "传入账号:mobile")
public R captcha(@RequestParam String mobile) {
// 验证短信限时发送次数验证
// 获取该号码短信的发送次数
Object o = redisUtil.get(GlobalConstant.CACHE_COUNT_SMS_CODE_PREFIX + mobile);
int sendCount = NumberUtils.toInt(String.valueOf(o));
if (o == null) {
// 未发送过验证码,初始化
redisUtil.set(GlobalConstant.CACHE_COUNT_SMS_CODE_PREFIX + mobile, 1, smsConfig.getLimitTime() * 3600);
} else if (sendCount > smsConfig.getLimitCount()) {
// 发送次数超过限制
return R.error("发送验证码次数达上限,请稍后再试!");
} else {
// 更新发送次数
long expire = redisUtil.getExpire(GlobalConstant.CACHE_COUNT_SMS_CODE_PREFIX + mobile);
redisUtil.set(GlobalConstant.CACHE_COUNT_SMS_CODE_PREFIX + mobile, sendCount + 1, expire);
}
//生成六位数的字符串
String code = RandomUtils.nextInt(100000, 999999) + StringPool.EMPTY;
smsSender.sendCaptcha(mobile, code);
redisUtil.set(GlobalConstant.CAPTCHA + StringPool.UNDERSCORE + mobile, code, 60L);
return R.ok(Boolean.TRUE);
}
/**
* 验证码
*/
@PostMapping("/captcha")
@XjrLog(value = "验证码登录")
public R loginByCaptcha(@RequestBody LoginCaptchaDto loginCaptchaDto) {
String mobile = loginCaptchaDto.getMobile();
String code = redisUtil.get(GlobalConstant.CAPTCHA + StringPool.UNDERSCORE + mobile);
if (code != null && StringUtils.equals(code, loginCaptchaDto.getCode())) {
User user = userClient.getUserByMobileFeign(mobile);
if (user == null) {
return R.error("用户不存在!");
}
if (user.getEnabledMark() == EnabledMark.DISABLED.getCode()) {
return R.error("账户未启用");
}
//此登录接口登录web端
StpUtil.login(user.getId(), "PC");
SaSession tokenSession = StpUtil.getTokenSession();
tokenSession.set(GlobalConstant.LOGIN_USER_INFO_KEY, user);
Map<String, Object> vo = new HashMap<>(1);
vo.put(GlobalConstant.TOKEN_KEY, StpUtil.getTokenValue());
return R.ok(vo);
}
return R.error("验证码不存在!");
}
/**
* 退出
*/
@PostMapping("/logout")
public R logout() {
StpUtil.logout();
return R.ok("登出成功!");
}
@PostMapping("/token")
@Operation(summary = "根据keycloak-token 登录", description = "传入keycloak-token")
@XjrLog(value = "keycloak-token登录成功")
public R loginByToken(@RequestBody KeyCloakLoginInfoDto dto) {
Map<String, Object> credentialsMap = new HashMap<>(1);
credentialsMap.put("secret", keyCloakConfig.getSecret());
Configuration configuration = new Configuration(keyCloakConfig.getUrl(), keyCloakConfig.getRealm(), keyCloakConfig.getClientId(), credentialsMap, null);
AuthzClient authzClient = AuthzClient.create(configuration);
AccessTokenResponse response = authzClient.obtainAccessToken(keyCloakConfig.getUserName(), keyCloakConfig.getPassword());
if (StrUtil.isNotBlank(response.getError())) {
return R.error(response.getError());
}
//TODO keycloak 登陆过 解析token获取数据 做框架登录操作
JWT jwt = JWTUtil.parseToken(dto.getToken());
Object code = jwt.getPayload(keyCloakConfig.getPayload());
User user = userClient.getUserByCodeFeign(String.valueOf(code));
List<LoginConfig> list = loginConfigClient.getAllListFeign();
if (list.size() == 0){//如果没有,则设置为默认配置,并进行保存
LoginConfig loginConfig = new LoginConfig();
loginConfig.setId(1L);
loginConfig.setMulLogin("0,1");
loginConfig.setMutualExclusion(YesOrNoEnum.YES.getCode());
loginConfig.setWithoutLogin(YesOrNoEnum.YES.getCode());
loginConfig.setPasswordStrategy(YesOrNoEnum.YES.getCode());
loginConfig.setStrategyMaxNumber(7);
list.add(loginConfig);
loginConfigClient.addLoginConfigFeign(loginConfig);
}
LoginConfig loginConfig = list.get(0);
if (user == null) {
return R.error("帐号密码错误!");
} else if (!Integer.valueOf(1).equals(user.getEnabledMark())) {
return R.error("当前账号已被锁定,请联系管理员!");
}
if (StrUtil.isNotBlank(dto.getDevice()) && dto.getDevice() == "PC" && !loginConfig.getMulLogin().contains("0")){
throw new MyException("当前Web端登录未授权请联系管理员");
}else if (StrUtil.isNotBlank(dto.getDevice()) && dto.getDevice() == "APP" && !loginConfig.getMulLogin().contains("1")){
throw new MyException("当前APP端登录未授权请联系管理员");
}else {
if (StrUtil.isBlank(loginConfig.getMulLogin()) || !loginConfig.getMulLogin().contains("0")){
throw new MyException("当前Web端登录未授权请联系管理员");
}
}
SaTokenConfig oldConfig = SaManager.getConfig();
if (loginConfig.getMutualExclusion() == YesOrNoEnum.NO.getCode()){
//不开启同端互斥
oldConfig.setIsConcurrent(true);
}else {
//开启同端互斥
oldConfig.setIsConcurrent(false);
}
// 注入到 SaManager 中
SaManager.setConfig(oldConfig);
if (loginConfig.getWithoutLogin() == YesOrNoEnum.YES.getCode()){//开启就设置为7天免登录
StpUtil.login(user.getId(),new SaLoginModel().setDevice(dto.getDevice()).setTimeout(60 * 60 * 24 * 7));
}else {
//此登录接口登录web端,IsLastingCookie设置为false也就是关闭浏览器后再次打开需要重新登录
StpUtil.login(user.getId(), new SaLoginModel().setDevice(dto.getDevice()).setIsLastingCookie(false));
}
SaSession tokenSession = StpUtil.getTokenSession();
tokenSession.set(GlobalConstant.LOGIN_USER_INFO_KEY, user);
Map<String, Object> vo = new HashMap<>(1);
vo.put(GlobalConstant.TOKEN_KEY, StpUtil.getTokenValue());
return R.ok("登录成功!", vo);
}
@PostMapping("/qrcode-login")
@Operation(summary = "oauth 扫码登录", description = "oauth 扫码登录")
@XjrLog(value = "oauth 扫码登录")
public R createAuthorizeUrl(@Valid @RequestBody CreateAuthorizeUrlDto dto){
AuthRequest authRequest = oauthClient.getAuthRequest(dto.getSource());
String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
return R.ok(authorizeUrl);
}
}