spring security 之通过 token 验证用户保持登录状态

第一次使用 springSecurity,采用前后端分离的方式,vue 开发 Web 端通过正常方式访问,App 端需要设计为不强制登录(只要不是 App 安装、版本更新、注销登录,在第一次登录后就不需要再次登录)。由于 security 默认的登录方式不支持这种方式,需要重写过滤器,修改为支持从 header 中获取 token 值,根据 token 设置当前登录对象。
思路大概为:App 端登录成功,后端返回 token 值,App 保存在本地后在后面的每次请求中都在 header 中带着 token 进行请求。后端重写过滤器,在过滤器中解析 token 值并将 token 中带的对象放到登录用户中,让 security 认为请求已经是在登录状态下进行。

1、新建AuthenticationTokenFilter继承OncePerRequestFilter,重写doFilterInternal方法。在doFilterInternal中获取 header 中带着的验证信息,解析 token 值获取用户信息,并将用户信息设置到SecurityContextHolder中。

 

@Component  
public class AuthenticationTokenFilter extends OncePerRequestFilter {  
  
      
    @Autowired  
  private UserService userService; //用户信息service  
  
  @Override  
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {  
        String authHeader = request.getHeader("token");//获取header中的验证信息  
  
  if (authHeader != null && authHeader.startsWith("Bearer ")) {  
            final String authToken = authHeader.substring("Bearer ".length());  
  
  String username = JwtUtils.parseToken(authToken, "\_secret"); //从token中获取用户信息,jwtUtils自定义的token加解密方式  
  
  if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {  
                UserDetails userDetails = userService.loadUserByUsername(username);//根据用户名获取用户对象  
  
  if (userDetails != null) {  
                    UsernamePasswordAuthenticationToken authentication =  
                            new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());  
  authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));  
  //设置为已登录  
  SecurityContextHolder.getContext().setAuthentication(authentication);  
  }  
            }  
        }  
  
        chain.doFilter(request, response);  
  }  
}

2、在继承了WebSecurityConfigurerAdapter的类中增加以下内容

 
@Autowired AuthenticationTokenFilter authenticationTokenFilter; // token 拦截器 
 
@Override protected void configure(HttpSecurity http) throws Exception { // 加上addFilterBefore执行token拦截器 http .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class) ...



作者:524021835
链接:https://hacpai.com/article/1545318463746
来源:黑客派
协议:CC BY-SA 4.0 https://creativecommons.org/licenses/by-sa/4.0/

posted @ 2020-01-03 23:26  N神3  阅读(13800)  评论(1编辑  收藏  举报