You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
8.6 KiB

package com.epmet.auth;
import com.epmet.commons.tools.constant.AppClientConstant;
import com.epmet.commons.tools.constant.Constant;
import com.epmet.commons.tools.exception.EpmetErrorCode;
import com.epmet.commons.tools.exception.RenException;
import com.epmet.commons.tools.security.dto.BaseTokenDto;
import com.epmet.commons.tools.security.dto.GovTokenDto;
import com.epmet.commons.tools.security.dto.TokenDto;
import com.epmet.commons.tools.utils.CpUserDetailRedis;
import com.epmet.filter.CpProperty;
import com.epmet.jwt.JwtTokenUtils;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
/**
* 内部认证处理器
*/
@Component
public class InternalAuthProcessor extends AuthProcessor {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private JwtTokenUtils jwtTokenUtils;
@Autowired
private CpUserDetailRedis cpUserDetailRedis;
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
@Autowired
private CpProperty cpProperty;
@Override
public ServerWebExchange auth(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String requestUri = request.getPath().pathWithinApplication().value();
String token = getTokenFromRequest(request);
//BaseTokenDto baseTokenDto = StringUtils.isNotBlank(token) ? getBaseTokenDto(token, jwtTokenUtils) : null;
BaseTokenDto baseTokenDto;
if(StringUtils.isNotBlank(token)){
try{
baseTokenDto = getBaseTokenDto(token, jwtTokenUtils);
}catch(RenException e){
//return response(exchange,new Result<>().error(e.getCode(),e.getMsg()));
throw new RenException(e.getCode(), e.getInternalMsg());
}
}else{
baseTokenDto = null;
}
String customerId = "";
if (baseTokenDto != null) {
if (AppClientConstant.APP_RESI.equals(baseTokenDto.getApp())) {
// 居民端
TokenDto resiTokenDto = getLoginUserInfoByToken(token, jwtTokenUtils, TokenDto.class);
if (resiTokenDto != null) {
customerId = resiTokenDto.getCustomerId();
baseTokenDto = resiTokenDto;
}
} else if (AppClientConstant.APP_GOV.equals(baseTokenDto.getApp())) {
// 政府端
GovTokenDto govTokenDto = getLoginUserInfoByToken(token, jwtTokenUtils, GovTokenDto.class);
if (govTokenDto != null) {
customerId = govTokenDto.getCustomerId();
baseTokenDto = govTokenDto;
}
} else if(AppClientConstant.APP_OPER.equals(baseTokenDto.getApp())){
//运营端
TokenDto resiTokenDto = getLoginUserInfoByToken(token, jwtTokenUtils, TokenDto.class);
if (resiTokenDto != null) {
customerId = resiTokenDto.getCustomerId();
baseTokenDto = resiTokenDto;
}
}
}
if (needAuth(requestUri)) {
// 校验token
if (StringUtils.isBlank(token)) {
//return response(exchange, new Result<>().error(EpmetErrorCode.ERR10005.getCode(), EpmetErrorCode.ERR10005.getMsg()));
throw new RenException(EpmetErrorCode.ERR10005.getCode(), EpmetErrorCode.ERR10005.getMsg());
}
try {
validateTokenDto(baseTokenDto, token);
} catch (RenException e) {
//return response(exchange, new Result<>().error(e.getCode(), e.getMsg()));
throw new RenException(e.getCode(), e.getInternalMsg());
}
}
// 添加header
if (baseTokenDto != null) {
String redisKey = baseTokenDto.getApp() + "-" + baseTokenDto.getClient() + "-" + baseTokenDto.getUserId();
logger.info("redisKey=" + redisKey);
ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
builder.header(Constant.APP_USER_KEY, redisKey);
builder.header(AppClientConstant.APP,baseTokenDto.getApp());
builder.header(AppClientConstant.CLIENT,baseTokenDto.getClient());
builder.header(AppClientConstant.USER_ID,baseTokenDto.getUserId());
if(StringUtils.isNotBlank(customerId)){
if (StringUtils.equalsAny(baseTokenDto.getApp(), AppClientConstant.APP_GOV, AppClientConstant.APP_RESI, "public")) {//工作端/居民端
builder.header(AppClientConstant.CUSTOMER_ID, customerId);
}
}
//if (StringUtils.isNotBlank(baseTokenDto.getCustomerId())) {
// builder.header(AppClientConstant.CUSTOMER_ID,baseTokenDto.getCustomerId());
//}
//
//if (StringUtils.equalsAny(baseTokenDto.getApp(), AppClientConstant.APP_GOV, AppClientConstant.APP_RESI)) {//工作端/居民端
// if(StringUtils.isNotBlank(customerId)){
// exchange.getRequest().mutate().header(AppClientConstant.CUSTOMER_ID, customerId);
// }
//} else if (StringUtils.equals(baseTokenDto.getApp(), "public")) {//公众号端
// exchange.getRequest().mutate().header(AppClientConstant.CUSTOMER_ID, customerId);
//}
ServerHttpRequest build = exchange.getRequest().mutate().build();
return exchange.mutate().request(build).build();
}
return exchange;
}
/**
* 是否需要认证
* @param requestUri
* @return
*/
private boolean needAuth(String requestUri) {
for (String url : cpProperty.getInternalAuthUrlsWhiteList()) {
if (antPathMatcher.match(url, requestUri)) {
return false;
}
}
for (String url : cpProperty.getInternalAuthUrls()) {
if (antPathMatcher.match(url, requestUri)) {
return true;
}
}
return false;
}
/**
* 从请求中获取token
* @param request
* @return
*/
private String getTokenFromRequest(ServerHttpRequest request) {
HttpHeaders headers = request.getHeaders();
String token = headers.getFirst(Constant.AUTHORIZATION_HEADER);
if (StringUtils.isBlank(token)) {
token = headers.getFirst(Constant.TOKEN_HEADER);
}
if (StringUtils.isBlank(token)) {
token = request.getQueryParams().getFirst(Constant.AUTHORIZATION_HEADER);
}
return token;
}
private BaseTokenDto getBaseTokenDto(String token, JwtTokenUtils jwtTokenUtils) {
//是否过期
Claims claims = jwtTokenUtils.getClaimByToken(token);
if (claims == null || jwtTokenUtils.isTokenExpired(claims.getExpiration())) {
return null;
}
//获取用户ID
String app = (String) claims.get("app");
String client = (String) claims.get("client");
String userId = (String) claims.get("userId");
return new BaseTokenDto(app, client, userId, token);
}
private <T> T getLoginUserInfoByToken(String token, JwtTokenUtils jwtTokenUtils, Class<T> clz) {
BaseTokenDto baseTokenDto = getBaseTokenDto(token, jwtTokenUtils);
//查询Redis
return cpUserDetailRedis.get(baseTokenDto.getApp(), baseTokenDto.getClient(), baseTokenDto.getUserId(), clz);
}
/**
* 校验Token是否异常
* @param tokenDto
* @param tokenStr
*/
private void validateTokenDto(BaseTokenDto tokenDto, String tokenStr) {
if (null == tokenDto) {
//说明登录状态时效(超时)
throw new RenException(EpmetErrorCode.ERR10006.getCode());
}else{
//Redis中存在数据,取出token,进行比对
if(StringUtils.equals(tokenDto.getToken(),tokenStr)){
//用户携带token与Redis中一致
}else{
//用户携带token与Redis中不一致,说明当前用户此次会话失效,提示重新登陆
throw new RenException(EpmetErrorCode.ERR10007.getCode());
}
}
}
}