【8.0.2】【auth】更新Token登录业务

pull/57/MERGE
fengshuonan 2023-11-07 14:04:14 +08:00
parent 34ec18bef5
commit cd7374b3e9
5 changed files with 114 additions and 43 deletions

View File

@ -27,9 +27,9 @@ package cn.stylefeng.roses.kernel.auth.api;
import cn.stylefeng.roses.kernel.auth.api.exception.AuthException; import cn.stylefeng.roses.kernel.auth.api.exception.AuthException;
import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginRequest; import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginRequest;
import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginResponse; import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginResponse;
import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginWithTokenRequest;
import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser; import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser;
import cn.stylefeng.roses.kernel.auth.api.pojo.payload.DefaultJwtPayload; import cn.stylefeng.roses.kernel.auth.api.pojo.payload.DefaultJwtPayload;
import cn.stylefeng.roses.kernel.auth.api.pojo.sso.LoginBySsoTokenRequest;
/** /**
* 退token * 退token
@ -75,7 +75,7 @@ public interface AuthServiceApi {
* @author fengshuonan * @author fengshuonan
* @since 2021/5/25 22:44 * @since 2021/5/25 22:44
*/ */
LoginResponse LoginWithToken(LoginWithTokenRequest loginWithTokenRequest); LoginResponse LoginByCaToken(LoginBySsoTokenRequest loginWithTokenRequest);
/** /**
* 退 * 退

View File

@ -0,0 +1,46 @@
package cn.stylefeng.roses.kernel.auth.api.pojo.sso;
import lombok.Data;
import java.util.Map;
/**
*
*
* @author fengshuonan
* @date 2021/1/21 14:04
*/
@Data
public class DecryptCaLoginUser {
/**
* token
*/
private String caToken;
/**
* id
*/
private Long tenantId;
/**
* id
*/
private Long userId;
/**
*
*/
private String account;
/**
*
*/
private String realName;
/**
*
*/
private Map<String, Object> otherProperties;
}

View File

@ -0,0 +1,33 @@
package cn.stylefeng.roses.kernel.auth.api.pojo.sso;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* SSO token
*
* @author fengshuonan
* @since 2023/11/5 12:31
*/
@Data
@AllArgsConstructor
public class DecryptCaTokenInfo {
/**
* token
*/
private String caToken;
/**
* id
*/
private DecryptCaLoginUser caLoginUser;
/**
* token
* <p>
* yyyyMMddHHmmss
*/
private String generationDateTime;
}

View File

@ -1,4 +1,4 @@
package cn.stylefeng.roses.kernel.auth.api.pojo.auth; package cn.stylefeng.roses.kernel.auth.api.pojo.sso;
import cn.stylefeng.roses.kernel.rule.pojo.request.BaseRequest; import cn.stylefeng.roses.kernel.rule.pojo.request.BaseRequest;
import lombok.Data; import lombok.Data;
@ -14,7 +14,7 @@ import javax.validation.constraints.NotBlank;
*/ */
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Data @Data
public class LoginWithTokenRequest extends BaseRequest { public class LoginBySsoTokenRequest extends BaseRequest {
/** /**
* token * token

View File

@ -25,6 +25,9 @@
package cn.stylefeng.roses.kernel.auth.auth; package cn.stylefeng.roses.kernel.auth.auth;
import cn.hutool.core.codec.Base64; import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
@ -39,25 +42,24 @@ import cn.stylefeng.roses.kernel.auth.api.exception.enums.AuthExceptionEnum;
import cn.stylefeng.roses.kernel.auth.api.expander.AuthConfigExpander; import cn.stylefeng.roses.kernel.auth.api.expander.AuthConfigExpander;
import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginRequest; import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginRequest;
import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginResponse; import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginResponse;
import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginWithTokenRequest;
import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser; import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser;
import cn.stylefeng.roses.kernel.auth.api.pojo.payload.DefaultJwtPayload; import cn.stylefeng.roses.kernel.auth.api.pojo.payload.DefaultJwtPayload;
import cn.stylefeng.roses.kernel.auth.api.pojo.sso.DecryptCaLoginUser;
import cn.stylefeng.roses.kernel.auth.api.pojo.sso.DecryptCaTokenInfo;
import cn.stylefeng.roses.kernel.auth.api.pojo.sso.LoginBySsoTokenRequest;
import cn.stylefeng.roses.kernel.cache.api.CacheOperatorApi; import cn.stylefeng.roses.kernel.cache.api.CacheOperatorApi;
import cn.stylefeng.roses.kernel.demo.expander.DemoConfigExpander; import cn.stylefeng.roses.kernel.demo.expander.DemoConfigExpander;
import cn.stylefeng.roses.kernel.jwt.JwtTokenOperator;
import cn.stylefeng.roses.kernel.jwt.api.JwtApi; import cn.stylefeng.roses.kernel.jwt.api.JwtApi;
import cn.stylefeng.roses.kernel.jwt.api.exception.JwtException; import cn.stylefeng.roses.kernel.jwt.api.exception.JwtException;
import cn.stylefeng.roses.kernel.jwt.api.exception.enums.JwtExceptionEnum; import cn.stylefeng.roses.kernel.jwt.api.exception.enums.JwtExceptionEnum;
import cn.stylefeng.roses.kernel.jwt.api.pojo.config.JwtConfig;
import cn.stylefeng.roses.kernel.log.api.LoginLogServiceApi; import cn.stylefeng.roses.kernel.log.api.LoginLogServiceApi;
import cn.stylefeng.roses.kernel.sys.api.SysUserServiceApi; import cn.stylefeng.roses.kernel.sys.api.SysUserServiceApi;
import cn.stylefeng.roses.kernel.sys.api.pojo.user.UserValidateDTO; import cn.stylefeng.roses.kernel.sys.api.pojo.user.UserValidateDTO;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Claims;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Date;
import static cn.stylefeng.roses.kernel.auth.api.exception.enums.AuthExceptionEnum.AUTH_EXPIRED_ERROR; import static cn.stylefeng.roses.kernel.auth.api.exception.enums.AuthExceptionEnum.AUTH_EXPIRED_ERROR;
import static cn.stylefeng.roses.kernel.auth.api.exception.enums.AuthExceptionEnum.TOKEN_PARSE_ERROR; import static cn.stylefeng.roses.kernel.auth.api.exception.enums.AuthExceptionEnum.TOKEN_PARSE_ERROR;
@ -112,52 +114,42 @@ public class AuthServiceImpl implements AuthServiceApi {
} }
@Override @Override
public LoginResponse LoginWithToken(LoginWithTokenRequest loginWithTokenRequest) { public LoginResponse LoginByCaToken(LoginBySsoTokenRequest loginWithTokenRequest) {
// 解析jwt token中的账号 // sso token是一个加密的字符串需要用AES秘钥对称解密
JwtConfig jwtConfig = new JwtConfig(); String encryptUserInfo = loginWithTokenRequest.getToken();
jwtConfig.setJwtSecret(AuthConfigExpander.getSsoJwtSecret());
jwtConfig.setExpiredSeconds(0L);
// jwt工具类初始化 // aes解密出用户信息
JwtTokenOperator jwtTokenOperator = new JwtTokenOperator(jwtConfig); AES aesUtil = SecureUtil.aes(Base64.decode(AuthConfigExpander.getSsoDataDecryptSecret()));
String userInfoJson = aesUtil.decryptStr(encryptUserInfo, CharsetUtil.CHARSET_UTF_8);
// 解析token中的用户信息 // 转化为实体类
Claims payload = null; DecryptCaTokenInfo decryptCaTokenInfo = JSON.parseObject(userInfoJson, DecryptCaTokenInfo.class);
try {
payload = jwtTokenOperator.getJwtPayloadClaims(loginWithTokenRequest.getToken()); // 如果时间大于2分钟则认定token过期
} catch (Exception exception) { String tokenGenerateTimeStr = decryptCaTokenInfo.getGenerationDateTime();
throw new AuthException(AuthExceptionEnum.SSO_TOKEN_PARSE_ERROR, exception.getMessage()); DateTime tokenGenerateTime = DateUtil.parse(tokenGenerateTimeStr);
DateTime tokenExpTime = tokenGenerateTime.offset(DateField.MINUTE, 2);
if (tokenExpTime.isBefore(new Date())) {
throw new AuthException(AuthExceptionEnum.SSO_TOKEN_PARSE_ERROR, "sso token过期");
} }
// 获取到用户信息 // 获取token中的用户信息
Object userInfoEncryptString = payload.get("userInfo"); DecryptCaLoginUser caLoginUser = decryptCaTokenInfo.getCaLoginUser();
if (ObjectUtil.isEmpty(userInfoEncryptString)) { if (caLoginUser == null) {
throw new AuthException(AuthExceptionEnum.SSO_TOKEN_GET_USER_ERROR); throw new AuthException(AuthExceptionEnum.SSO_TOKEN_GET_USER_ERROR);
} }
// 解密出用户账号和caTokencaToken用于校验用户是否在单点中心 // 解密出用户账号和caTokencaToken用于校验用户是否在单点中心
String account = null; if (ObjectUtil.isEmpty(caLoginUser.getAccount()) || ObjectUtil.isEmpty(caLoginUser.getCaToken())) {
String caToken = null; throw new AuthException(AuthExceptionEnum.SSO_TOKEN_GET_USER_ERROR);
try {
AES aesUtil = SecureUtil.aes(Base64.decode(AuthConfigExpander.getSsoDataDecryptSecret()));
String loginUserJson = aesUtil.decryptStr(userInfoEncryptString.toString(), CharsetUtil.CHARSET_UTF_8);
JSONObject userInfoJsonObject = JSON.parseObject(loginUserJson);
account = userInfoJsonObject.getString("account");
caToken = userInfoJsonObject.getString("caToken");
} catch (Exception exception) {
throw new AuthException(AuthExceptionEnum.SSO_TOKEN_DECRYPT_USER_ERROR, exception.getMessage());
} }
// 账号为空,抛出异常 // 通过账号和caToken登录
if (account == null) { LoginResponse loginResponse = loginWithUserNameAndCaToken(caLoginUser.getAccount(), caLoginUser.getCaToken());
throw new AuthException(AuthExceptionEnum.SSO_TOKEN_DECRYPT_USER_ERROR);
}
LoginResponse loginResponse = loginWithUserNameAndCaToken(account, caToken); // 存储单点token和生成的本地token的映射关系用在远程退出的时将本地缓存清空
caClientTokenCacheApi.put(caLoginUser.getCaToken(), loginResponse.getToken());
// 存储单点token和生成的本地token的映射关系
caClientTokenCacheApi.put(loginWithTokenRequest.getToken(), loginResponse.getToken());
return loginResponse; return loginResponse;
} }