forked from luyan/epmet-cloud-lingshan
8 changed files with 320 additions and 237 deletions
@ -0,0 +1,26 @@ |
|||||
|
package com.epmet.auth; |
||||
|
|
||||
|
import com.alibaba.fastjson.JSON; |
||||
|
import org.springframework.cloud.gateway.filter.GatewayFilterChain; |
||||
|
import org.springframework.core.io.buffer.DataBuffer; |
||||
|
import org.springframework.http.HttpStatus; |
||||
|
import org.springframework.http.MediaType; |
||||
|
import org.springframework.web.server.ServerWebExchange; |
||||
|
import reactor.core.publisher.Flux; |
||||
|
import reactor.core.publisher.Mono; |
||||
|
|
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
|
||||
|
public abstract class AuthProcessor { |
||||
|
|
||||
|
abstract Mono<Void> auth(ServerWebExchange exchange, GatewayFilterChain chain); |
||||
|
|
||||
|
protected Mono<Void> response(ServerWebExchange exchange, Object object) { |
||||
|
String json = JSON.toJSONString(object); |
||||
|
DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(json.getBytes(StandardCharsets.UTF_8)); |
||||
|
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8); |
||||
|
exchange.getResponse().setStatusCode(HttpStatus.OK); |
||||
|
return exchange.getResponse().writeWith(Flux.just(buffer)); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
package com.epmet.auth; |
||||
|
|
||||
|
import org.springframework.cloud.gateway.filter.GatewayFilterChain; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
import org.springframework.web.server.ServerWebExchange; |
||||
|
import reactor.core.publisher.Mono; |
||||
|
|
||||
|
/** |
||||
|
* 外部应用认证 |
||||
|
*/ |
||||
|
@Component |
||||
|
public class ExternalAuthProcessor extends AuthProcessor { |
||||
|
|
||||
|
@Override |
||||
|
public Mono<Void> auth(ServerWebExchange exchange, GatewayFilterChain chain) { |
||||
|
|
||||
|
|
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
} |
@ -0,0 +1,175 @@ |
|||||
|
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.commons.tools.utils.Result; |
||||
|
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.web.server.ServerWebExchange; |
||||
|
import reactor.core.publisher.Mono; |
||||
|
|
||||
|
/** |
||||
|
* 内部认证处理器 |
||||
|
*/ |
||||
|
@Component |
||||
|
public class InternalAuthProcessor extends AuthProcessor { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(getClass()); |
||||
|
|
||||
|
@Autowired |
||||
|
private JwtTokenUtils jwtTokenUtils; |
||||
|
|
||||
|
@Autowired |
||||
|
private CpUserDetailRedis cpUserDetailRedis; |
||||
|
|
||||
|
@Override |
||||
|
public Mono<Void> auth(ServerWebExchange exchange, GatewayFilterChain chain) { |
||||
|
ServerHttpRequest request = exchange.getRequest(); |
||||
|
String requestUri = request.getPath().pathWithinApplication().value(); |
||||
|
|
||||
|
logger.info("CpAuthGatewayFilterFactory当前requestUri=[" + requestUri + "]CpAuthGatewayFilterFactory拦截成功"); |
||||
|
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())); |
||||
|
} |
||||
|
}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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 校验token
|
||||
|
if (StringUtils.isBlank(token)) { |
||||
|
return response(exchange,new Result<>().error(EpmetErrorCode.ERR10005.getCode(),EpmetErrorCode.ERR10005.getMsg())); |
||||
|
} |
||||
|
try { |
||||
|
validateTokenDto(baseTokenDto, token); |
||||
|
} catch (RenException e) { |
||||
|
return response(exchange,new Result<>().error(e.getCode(),e.getMsg())); |
||||
|
} |
||||
|
|
||||
|
// 添加header
|
||||
|
if (baseTokenDto != null) { |
||||
|
String redisKey = baseTokenDto.getApp() + "-" + baseTokenDto.getClient() + "-" + baseTokenDto.getUserId(); |
||||
|
logger.info("redisKey=" + redisKey); |
||||
|
exchange.getRequest().mutate() |
||||
|
.header(Constant.APP_USER_KEY, redisKey) |
||||
|
.header(AppClientConstant.APP,baseTokenDto.getApp()) |
||||
|
.header(AppClientConstant.CLIENT,baseTokenDto.getClient()) |
||||
|
.header(AppClientConstant.USER_ID,baseTokenDto.getUserId()); |
||||
|
|
||||
|
if (StringUtils.equals(baseTokenDto.getApp(), "gov")) {//工作端
|
||||
|
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 chain.filter(exchange.mutate().request(build).build()); |
||||
|
} |
||||
|
|
||||
|
return chain.filter(exchange); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 从请求中获取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()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -1,35 +0,0 @@ |
|||||
package com.epmet.filter; |
|
||||
|
|
||||
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.utils.CpUserDetailRedis; |
|
||||
import com.epmet.jwt.JwtTokenUtils; |
|
||||
import io.jsonwebtoken.Claims; |
|
||||
|
|
||||
/** |
|
||||
* 用户token的过滤器接口,提供通用的默认方法 |
|
||||
*/ |
|
||||
public interface UserTokenFilter { |
|
||||
|
|
||||
default BaseTokenDto getBaseTokenDto(String token, JwtTokenUtils jwtTokenUtils) { |
|
||||
//是否过期
|
|
||||
Claims claims = jwtTokenUtils.getClaimByToken(token); |
|
||||
if (claims == null || jwtTokenUtils.isTokenExpired(claims.getExpiration())) { |
|
||||
// throw new RenException(EpmetErrorCode.ERR401.getCode());
|
|
||||
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); |
|
||||
} |
|
||||
|
|
||||
default <T> T getLoginUserInfoByToken(String token, JwtTokenUtils jwtTokenUtils, CpUserDetailRedis cpUserDetailRedis, Class<T> clz) { |
|
||||
BaseTokenDto baseTokenDto = getBaseTokenDto(token, jwtTokenUtils); |
|
||||
//查询Redis
|
|
||||
return cpUserDetailRedis.get(baseTokenDto.getApp(), baseTokenDto.getClient(), baseTokenDto.getUserId(), clz); |
|
||||
} |
|
||||
|
|
||||
} |
|
Loading…
Reference in new issue