CheckTokenAspect.java 6.07 KB
package com.lhcredit.framework.aspectj;

import com.lhcredit.common.utils.StringUtils;
import com.lhcredit.framework.aspectj.lang.annotation.CheckToken;
import com.lhcredit.framework.aspectj.lang.enums.DataSourceType;
import com.lhcredit.framework.datasource.DynamicDataSourceContextHolder;
import com.lhcredit.framework.web.domain.AjaxResult;
import com.lhcredit.project.business.frontUser.domain.FrontUserMon;
import com.lhcredit.project.business.frontUser.service.TokenManager;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.lhcredit.framework.web.domain.AjaxResult.Type.TOKEN_INVALID;
import static com.lhcredit.framework.web.domain.AjaxResult.Type.TOKEN_LESS;

@Aspect
@Component
public class
CheckTokenAspect {

    @Autowired
    private TokenManager tokenManager;
    @Autowired
    private RedisTemplate redisTemplate;
//    @Value("${tongzouToken}")
//    private String tongzouToken;//通州企业画像使用的开放token


    // 配置织入点
    @Pointcut("@annotation(com.lhcredit.framework.aspectj.lang.annotation.CheckToken)")
    public void TokenPointCut() {
    }

    @Around("TokenPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        Object[] param = point.getArgs();
        String[] parameterName = signature.getParameterNames();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Object[] params = point.getArgs();
        String[] parameterNames = signature.getParameterNames();

        String token = request.getHeader("authorization");
        String requestURI = request.getRequestURI();


        if (token == null || StringUtils.isEmpty(token)) {
            return new AjaxResult(TOKEN_LESS, "请先登录", null);
        } else {
            CheckToken checkToken = getAnnotationLog(point);
//            //企业画像token,需要设置访问接口
//            if (StringUtils.isNotEmpty(token)&&token.contains(tongzouToken)){
//                if (validURISuccess(requestURI)){
//                    System.out.println("================通州企业画像接口token验证通过============================");
//                    return point.proceed();
//                }
//            }
            //解决并发方案1  通过注解设置+setnx
            boolean concurrent = checkToken.concurrent();
            if (!concurrent){
                //验证多次请求  请求间隔2秒
                boolean verificationURL=verificationURL(token,requestURI);
                if(!verificationURL){
                    return AjaxResult.error("请求失败(存在并发)!");
                }
            }
            //解决并发方案2  通过setnx token+url+paramName.hash

            //验证失效token
            int InToken = tokenManager.getInoperativeToken(token);

            //验证正确token
            FrontUserMon user = tokenManager.getUserInfoByToken(token);
            if (user == null) {
                return new AjaxResult(TOKEN_INVALID, "请先登录", null);
            } else {
                tokenManager.refreshUserToken(token);
            }
        }
        return point.proceed();
    }

    public boolean verificationURL(String token,String requestURI){
        String key="verificationURL:"+token+":"+requestURI;
        return redisTemplate.opsForValue().setIfAbsent(key,"1",2, TimeUnit.SECONDS);
    }

    /**
     * 获取ip
     *
     * @param request
     * @return
     */
    public String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
    /**
     * 是否存在注解,如果存在就获取
     */
    private CheckToken getAnnotationLog(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null) {
            return method.getAnnotation(CheckToken.class);
        }
        return null;
    }
    //通州企业画像请求验证码的接口
    private boolean validURISuccess(String uri){
        List<String> strings = Arrays.asList("detilPageInfoForTZ","enterpriseMap","actualControl","equityPenetrationChart");
        for (String string : strings) {
            if (uri.contains(string)) {
                return true;
            }
        }
        return false;
    }
}