微服务版后端初始化

This commit is contained in:
yaoyn
2025-02-08 17:51:37 +08:00
parent 54af6be188
commit da009a7cc4
1897 changed files with 429541 additions and 81 deletions

View File

@ -0,0 +1,263 @@
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);
}
}