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