puzhibing
2023-10-08 22199bbdda579861736420fe26c2873ab0f5d21c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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);
    }
}