package com.xzx.gc.interceptor;
|
|
import cn.hutool.crypto.SecureUtil;
|
import cn.hutool.json.JSONUtil;
|
import com.xzx.gc.common.annotations.PassToken;
|
import com.xzx.gc.common.constant.Constants;
|
import com.xzx.gc.common.exception.RestException;
|
import com.xzx.gc.common.utils.*;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.ModelAndView;
|
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletResponse;
|
import java.lang.reflect.Method;
|
import java.util.ArrayList;
|
import java.util.List;
|
|
|
/**
|
* token验证拦截器
|
*
|
* @author zan.zhong
|
* @date 2018-07-08 20:41
|
*/
|
@Slf4j
|
@Component
|
public class AuthInterceptor implements HandlerInterceptor {
|
|
//接口超时时间60s
|
private static final int timeLimit = 60;
|
|
@Autowired
|
private TokenUtil tokenUtil;
|
|
@Autowired
|
private BusinessUtil businessUtil;
|
|
@Autowired
|
private RedisUtil redisUtil;
|
|
@Override
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object object) throws Exception {
|
|
log.debug("进行通用拦截器:{}",request.getRequestURI());
|
|
/**********请求参数***********************/
|
String token = request.getHeader("token");
|
String timestamp = request.getHeader("timestamp");
|
String nonce = request.getHeader("nonce");
|
String sign = request.getHeader("sign");
|
String version = request.getHeader("version");
|
String mobilePhone = request.getHeader("mobilePhone");
|
String userId = request.getHeader("userId");
|
String clientType = request.getHeader("clientType");
|
String authKey = request.getHeader("authKey");
|
//ip地址
|
String ip=IpUtils.getIpAddr(request);
|
|
LogUtils.setTraceId(LogUtils.TRACE_USER_ID,userId==null?"匿名":userId);
|
|
|
/********请求参数END***********************/
|
|
|
/********************忽略的请求********************/
|
|
if(SpringUtil.isDev()&&"true".equals(request.getHeader("swagger"))){
|
return true;
|
}
|
|
|
// 如果不是映射到方法直接通过或者是否有passtoken注释,有则跳过认证
|
if (!(object instanceof HandlerMethod)) {
|
return true;
|
}
|
HandlerMethod handlerMethod = (HandlerMethod) object;
|
Method method = handlerMethod.getMethod();
|
if (method.isAnnotationPresent(PassToken.class)) {
|
PassToken passToken = method.getAnnotation(PassToken.class);
|
if (passToken.required()) {
|
return true;
|
}
|
}
|
|
/**************请求头参数非空验证********************/
|
validHead(ip,token, timestamp, nonce, sign, version, mobilePhone, userId, clientType,authKey);
|
|
/***请求时间验证**************/
|
if (System.currentTimeMillis() - Long.parseLong(timestamp) > (timeLimit * 1000)) {
|
throw new RestException(-1, "网络中断,请重新刷新页面");
|
}
|
|
/***********签名验证*********************/
|
validSign(ip,token, timestamp, nonce, sign, clientType,version,authKey);
|
|
/*********************重复请求验证************************/
|
validNonce(ip,nonce, version, mobilePhone, userId);
|
|
/**token验证*/
|
validToken(token, version, mobilePhone, userId);
|
|
/*********传递信息**************/
|
request.setAttribute("userId",userId);
|
|
return true;
|
}
|
|
private void validNonce(String ip,String nonce, String version, String mobilePhone, String userId) {
|
String nonceKey=null;
|
nonceKey = Constants.REDIS_USER_KEY + "signNonce:"+userId;
|
String list = redisUtil.get(nonceKey);
|
if (StringUtils.isBlank(list)) {
|
List<String> nonceList = new ArrayList<>();
|
nonceList.add(nonce);
|
redisUtil.setex(nonceKey,JSONUtil.toJsonStr(nonceList),timeLimit);
|
} else {
|
List<String> objects = JSONUtil.parseArray(list).toList(String.class);
|
if (!objects.contains(nonce)) {
|
objects.add(nonce);
|
redisUtil.setex(nonceKey,JSONUtil.toJsonStr(objects),timeLimit);
|
} else {
|
LogUtils.writeIp(ip,"重复的请求");
|
throw new RestException(-1,"您操作过快,请稍后再试");
|
}
|
}
|
}
|
|
private void validSign(String ip,String token, String timestamp, String nonce, String sign, String clientType,String version,String authKey) {
|
String newTokenString="";
|
String newSign="";
|
if(businessUtil.isAuth(version)){
|
newTokenString = token + timestamp + nonce + "v1.1" + clientType +authKey+ Constants.SIGN_SECRET_NEW;
|
newSign=sign;
|
}else {
|
newTokenString = token + timestamp + nonce + "v1.1" + clientType + Constants.SIGN_SECRET;
|
newSign = SecureUtil.md5(newTokenString).toUpperCase();
|
}
|
if (!newSign.equals(sign)) {
|
LogUtils.writeIp(ip,"签名不一致");
|
throw new RestException(-2,"签名不一致");
|
}
|
}
|
|
private void validHead(String ip,String token, String timestamp, String nonce, String sign, String version, String mobilePhone, String userId, String clientType,String authKey) {
|
if (StringUtils.isEmpty(token)) {
|
LogUtils.writeIp(ip,"请求头缺失token参数");
|
throw new RestException(-2, "请求头参数不正确");
|
}else if( StringUtils.isEmpty(timestamp)){
|
LogUtils.writeIp(ip,"请求头缺失timestamp参数");
|
throw new RestException(-2, "请求头参数不正确");
|
}else if(StringUtils.isEmpty(nonce)){
|
LogUtils.writeIp(ip,"请求头缺失nonce参数");
|
throw new RestException(-2, "请求头参数不正确");
|
}else if(StringUtils.isEmpty(sign) ){
|
LogUtils.writeIp(ip,"请求头缺失sign参数");
|
throw new RestException(-2, "请求头参数不正确");
|
}else if(StringUtils.isEmpty(version) ){
|
LogUtils.writeIp(ip,"请求头缺失version参数");
|
throw new RestException(-2, "请求头参数不正确");
|
}else if(StringUtils.isEmpty(clientType)){
|
LogUtils.writeIp(ip,"请求头缺失clientType参数");
|
throw new RestException(-2, "请求头参数不正确");
|
}else if(StringUtils.isBlank(userId)){
|
LogUtils.writeIp(ip,"请求头缺失userId参数");
|
throw new RestException(-2,"请求头参数不正确");
|
}else if (businessUtil.isAuth(version)) {
|
if(StringUtils.isBlank(authKey)){
|
LogUtils.writeIp(ip,"请求头缺失authKey参数");
|
throw new RestException(-2,"请求头参数不正确");
|
}
|
}
|
}
|
|
private void validToken(String token, String version, String mobilePhone, String userId) {
|
//验证token是否过期
|
if (tokenUtil.isExpire(userId)) {
|
throw new RestException(-2,"您的登录已经过期,请重新登录");
|
}
|
//验证token正确性
|
if(tokenUtil.verifier(token, userId)==-2){
|
if(!SpringUtil.isDev())
|
throw new RestException(-2, "您的登录已经过期,请重新登录");
|
}
|
//更新token有效时间
|
tokenUtil.updateTokenExpire(userId);
|
}
|
|
@Override
|
public void postHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
|
// //添加版本头用于更新
|
// Object versionServiceImpl = SpringUtil.getBean("versionServiceImpl");
|
// VersionInfo versionInfo=ReflectUtil.invoke(versionServiceImpl, "find");
|
// if(versionInfo!=null){
|
// httpServletResponse.addHeader("updateFlag",Convert.toStr(versionInfo.getUpdateFlag()));
|
// httpServletResponse.addHeader("forceUpdateFlag",Convert.toStr(versionInfo.getForceUpdateFlag()));
|
// httpServletResponse.addHeader("apkVersion",versionInfo.getApkMd5());
|
// }
|
}
|
|
@Override
|
public void afterCompletion(HttpServletRequest request, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
|
LogUtils.clearTraceId();
|
}
|
}
|