|
|
|
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(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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|