懒羊羊
2023-08-30 71e81ed1d12e4d69f53c8ad9e066650ad4186293
提交 | 用户 | 时间
71e81e 1 package cn.stylefeng.guns.sys.core.auth.filter;
2
3 import cn.stylefeng.guns.base.auth.jwt.JwtTokenUtil;
4 import cn.stylefeng.guns.sys.core.auth.cache.SessionManager;
5 import cn.stylefeng.guns.sys.core.auth.util.TokenUtil;
6 import cn.stylefeng.roses.core.util.ToolUtil;
7 import io.jsonwebtoken.JwtException;
8 import org.springframework.beans.factory.annotation.Autowired;
9 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
10 import org.springframework.security.core.context.SecurityContextHolder;
11 import org.springframework.security.core.userdetails.UserDetails;
12 import org.springframework.stereotype.Component;
13 import org.springframework.util.AntPathMatcher;
14 import org.springframework.web.filter.OncePerRequestFilter;
15
16 import javax.servlet.FilterChain;
17 import javax.servlet.ServletException;
18 import javax.servlet.http.Cookie;
19 import javax.servlet.http.HttpServletRequest;
20 import javax.servlet.http.HttpServletResponse;
21 import java.io.IOException;
22
23 import static cn.stylefeng.guns.base.consts.ConstantsContext.getTokenHeaderName;
24
25 /**
26  * 这个过滤器,在所有请求之前,也在spring security filters之前
27  * <p>
28  * 这个过滤器的作用是:接口在进业务之前,添加登录上下文(SecurityContext和LoginContext)
29  * <p>
30  * 因为现在的Guns没有用session了,只能token来校验当前的登录人的身份,所以在进业务之前要给当前登录人设置登录状态
31  *
32  * @author fengshuonan
33  * @Date 2019/7/20 21:33
34  */
35 @Component
36 public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
37
38     @Autowired
39     private SessionManager sessionManager;
40
41     public JwtAuthorizationTokenFilter() {
42     }
43
44     @Override
45     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
46
47         // 1.静态资源直接过滤,不走此过滤器
48         for (String reg : NoneAuthedResources.FRONTEND_RESOURCES) {
49             if (new AntPathMatcher().match(reg, request.getServletPath())) {
50                 chain.doFilter(request, response);
51                 return;
52             }
53         }
54
55         // 2.从cookie和header获取token
56         String authToken = TokenUtil.getToken();
57
58         // 3.通过token获取用户名
59         String username = null;
60         if (ToolUtil.isNotEmpty(authToken)) {
61             try {
62                 username = JwtTokenUtil.getJwtPayLoad(authToken).getAccount();
63             } catch (IllegalArgumentException | JwtException e) {
64                 //请求token为空或者token不正确,忽略,并不是所有接口都要鉴权
65             }
66         }
67
68         // 4.如果账号不为空,并且没有设置security上下文
69         if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
70
71             // 5.从缓存中拿userDetails,如果不为空,就设置登录上下文和权限上下文
72             UserDetails userDetails = sessionManager.getSession(authToken);
73             if (userDetails != null) {
74                 UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
75                         userDetails, null, userDetails.getAuthorities());
76                 SecurityContextHolder.getContext().setAuthentication(authentication);
77
78                 chain.doFilter(request, response);
79                 return;
80             } else {
81
82                 // 6.当用户的token过期了,缓存中没有用户信息,则删除相关cookies
83                 Cookie[] tempCookies = request.getCookies();
84                 if (tempCookies != null) {
85                     for (Cookie cookie : tempCookies) {
86                         if (getTokenHeaderName().equals(cookie.getName())) {
87                             Cookie temp = new Cookie(cookie.getName(), "");
88                             temp.setMaxAge(0);
89                             temp.setPath("/");
90                             response.addCookie(temp);
91                         }
92                     }
93                 }
94
95                 //如果是不需要权限校验的接口不需要返回session超时
96                 for (String reg : NoneAuthedResources.BACKEND_RESOURCES) {
97                     if (new AntPathMatcher().match(reg, request.getServletPath())) {
98                         chain.doFilter(request, response);
99                         return;
100                     }
101                 }
102
103                 //跳转到登录超时
104                 response.setHeader("Guns-Session-Timeout", "true");
105                 request.getRequestDispatcher("/global/sessionError").forward(request, response);
106             }
107         }
108
109         chain.doFilter(request, response);
110     }
111 }