package com.sinata.rest.modular.auth.filter;
|
|
import com.sinata.common.enums.EnumRedisKey;
|
import com.sinata.rest.common.exception.BizExceptionEnum;
|
import com.sinata.rest.config.properties.JwtProperties;
|
import com.sinata.rest.core.tips.ErrorTip;
|
import com.sinata.rest.core.util.RenderUtil;
|
import com.sinata.rest.modular.auth.model.AccountVo;
|
import com.sinata.rest.modular.auth.util.JwtTokenUtil;
|
import com.sinata.rest.modular.auth.util.ThreadPoolUtil;
|
import com.sinata.rest.modular.system.service.RedisTemplateService;
|
import io.jsonwebtoken.JwtException;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.util.StringUtils;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
|
import javax.annotation.Resource;
|
import javax.servlet.FilterChain;
|
import javax.servlet.ServletException;
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletResponse;
|
import java.io.IOException;
|
import java.util.Objects;
|
|
/**
|
* 对客户端请求的jwt token验证过滤器
|
*/
|
@Slf4j
|
public class AuthFilter extends OncePerRequestFilter {
|
|
@Resource
|
private RedisTemplateService redisTemplateService;
|
|
@Autowired
|
private JwtTokenUtil jwtTokenUtil;
|
|
@Autowired
|
private JwtProperties jwtProperties;
|
|
@Override
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
|
// 解决web端跨域问题
|
String originHeader = request.getHeader("Origin");
|
response.setHeader("Access-Control-Allow-Origin", originHeader);
|
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
|
response.setHeader("Access-Control-Max-Age", "0");
|
response.setHeader("Access-Control-Allow-Headers", "Authorization,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");
|
response.setHeader("Access-Control-Allow-Credentials", "true");
|
response.setHeader("XDomainRequestAllowed", "1");
|
|
//log.error("{}请求地址:{}", request.getMethod(), request.getServletPath());
|
|
String[] authPath = jwtProperties.getAuthPath().split(",");
|
for (int i = 0; i < authPath.length; i++) {
|
if (request.getServletPath().contains(authPath[i].trim())) {
|
chain.doFilter(request, response);
|
return;
|
}
|
}
|
|
final String requestHeader = request.getHeader(jwtProperties.getHeader());
|
String authToken = null;
|
if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
|
authToken = requestHeader.substring(7);
|
try {
|
String redisTokenOpen = redisTemplateService.stringGetStringByKey(EnumRedisKey.REDIS_TOKEN_OPEN.index);
|
// 判断配置,是否开启Redis中token验证开关
|
if (redisTokenOpen != null && redisTokenOpen.equals("true")) {
|
String userId = null;
|
try {
|
userId = jwtTokenUtil.getUsernameFromToken(authToken);
|
} catch (Exception e) {
|
//log.error("{}异常token:{}", requestHeader, authToken);
|
// 异常token
|
RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_EXPIRED.getCode(), BizExceptionEnum.TOKEN_EXPIRED.getMessage()));
|
return;
|
}
|
if (userId == null) {
|
log.debug("错误token:{}", authToken);
|
// 错误token
|
RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_EXPIRED.getCode(), BizExceptionEnum.TOKEN_EXPIRED.getMessage()));
|
return;
|
}
|
|
// 缓存中获取token
|
Object redisToken = redisTemplateService.hashGet(EnumRedisKey.TOKEN.index, userId);
|
redisToken = Objects.isNull(redisToken) ? redisTemplateService.hashGet(EnumRedisKey.TOKEN_SHOP.index, userId) : redisToken;
|
if (StringUtils.isEmpty(redisToken)) {
|
log.debug("用户{}为空token:{}", userId, authToken);
|
}
|
if (redisToken != null && !redisToken.toString().equals(authToken)) {
|
log.debug("用户{}无效token:{}===={}", userId, authToken, redisToken);
|
// 验证token无效
|
RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_EXPIRED.getCode(), BizExceptionEnum.TOKEN_EXPIRED.getMessage()));
|
return;
|
}
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
|
|
//验证token是否过期,包含了验证jwt是否正确
|
try {
|
boolean flag = jwtTokenUtil.isTokenExpired(authToken);
|
if (flag) {
|
RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_EXPIRED.getCode(), BizExceptionEnum.TOKEN_EXPIRED.getMessage()));
|
return;
|
}
|
} catch (JwtException e) {
|
System.out.println("鉴权失败:有异常就是token解析失败。" + request.getServletPath());
|
//有异常就是token解析失败
|
RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_ERROR.getCode(), BizExceptionEnum.TOKEN_ERROR.getMessage()));
|
return;
|
}
|
|
// 获取Token中账户ID
|
String accountId = jwtTokenUtil.getUsernameFromToken(authToken);
|
// 验证token信息,存入线程后面获取账户ID【ThreadPoolUtil.getUserId();】
|
if (!StringUtils.isEmpty(accountId)) {
|
ThreadPoolUtil.ACCOUNT_LOCAL.set(new AccountVo(Integer.parseInt(accountId)));
|
} else {
|
RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_ERROR.getCode(), BizExceptionEnum.TOKEN_EXPIRED.getMessage()));
|
return;
|
}
|
} else {
|
System.out.println("鉴权失败:header没有带Bearer字段。" + request.getServletPath());
|
//header没有带Bearer字段
|
RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_ERROR.getCode(), BizExceptionEnum.TOKEN_ERROR.getMessage()));
|
return;
|
}
|
chain.doFilter(request, response);
|
}
|
}
|