huliguo
2 天以前 5d7b65670282a4fad015e37d567cfa171b162052
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
package com.ruoyi.errand.interceptor;
 
 
 
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.errand.constant.AppUserStatusConstant;
import com.ruoyi.errand.constant.DelFlagConstant;
import com.ruoyi.errand.domain.AppUser;
import com.ruoyi.errand.mapper.AppUserMapper;
import com.ruoyi.errand.utils.JwtUtil;
import com.ruoyi.errand.utils.TokenBlacklistService;
import com.ruoyi.errand.utils.WeAppAuthenticationToken;
import com.ruoyi.errand.utils.WeAppSecurityProperties;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;
 
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令牌校验的拦截器
 */
@Component
@Slf4j
public class APPJwtTokenInterceptor  extends OncePerRequestFilter {
 
    @Autowired
    private WeAppSecurityProperties weAppSecurityProperties;
    @Autowired
    private TokenBlacklistService tokenBlacklistService;
 
 
 
    @Autowired
    private AppUserMapper appUserMapper;
    private static final PathMatcher pathMatcher = new AntPathMatcher();
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws IOException, ServletException {
        try {
            String path = request.getRequestURI();
            log.info("进入appJwt认证");
            // 检查是否在白名单中
            if (isExcludedPath(path)) {
                chain.doFilter(request, response);
                return;
            }
            //不是app开头的也不用校验
            if (!path.startsWith("/app")) {
                chain.doFilter(request, response);
                return;
            }
 
 
            // 从Header提取Token(如:Authorization: WeApp {token})
            String token = request.getHeader("Authorization");
            if (token == null || !token.startsWith("app:")) {
                throw new ServiceException("无效token", 401);
            }
            //解析token 获取userid,再查询到AppUser
            String realToken = token.substring(4);
            //查看是否在黑名单中
            if (tokenBlacklistService.isBlacklisted(realToken)) {
                throw new ServiceException("无效token", 401);
            }
            try {
 
                Claims claims = JwtUtil.parseJWT(realToken);
                String userId = claims.get("userId").toString();
                AppUser appUser = appUserMapper.selectById(userId);
                if (appUser == null || appUser.getDelFlag().equals(DelFlagConstant.DELETE)) {
                    throw new ServiceException("用户不存在", 401);
                }
                if (Objects.equals(appUser.getStatus(), AppUserStatusConstant.FREEZE)) {
                    throw new ServiceException("该账户已被冻结", 401);
                }
                if (Objects.equals(appUser.getStatus(), AppUserStatusConstant.LOGOUT)) {
                    throw new ServiceException("该账户已被注销", 401);
                }
                // 将userId存入SecurityContext(需自定义Authentication对象)
                WeAppAuthenticationToken authentication =
                        new WeAppAuthenticationToken(userId, appUser, token);
                SecurityContextHolder.getContext().setAuthentication(authentication);
                chain.doFilter(request, response);
            } catch (Exception e) {
                throw new ServiceException("TOKEN解析失败", 401);
            }
        }catch (ServiceException e) {
            response.setStatus(e.getCode() != null ? e.getCode() : 401);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(
                    String.format("{\"code\":%d,\"msg\":\"%s\"}",
                            e.getCode(), e.getMessage())
            );
            return;
        }catch (Exception e) {
            response.setStatus(401);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(
                    "{\"code\":500,\"msg\":\"系统内部错误\"}"
            );
            return;
        }
    }
    /**
     * 判断路径是否在白名单中
     */
    private boolean isExcludedPath(String requestPath) {
        return weAppSecurityProperties.getExcludeUrls().stream()
                .anyMatch(excludedPath ->
                        pathMatcher.match(excludedPath, requestPath)
                );
    }
}