1.背景
基于前后端分离项目的后端模块;
2.相关技术
springboot全家桶
- web模块
 - security模块;用于权限的验证
 - mongodb 模块;集成mogodb模块
 
jwt 用于token的生成
mongodb
lomok
后续会细分出更多的模块。用上springcloud全家桶
3.权限验证流程
3.1 构建User对象
实现security的UserDetail。之后所有权限获取都是从这个对象中返回
重写的默认属性必须返回true,不然在登录那块验证该属性是不是true。如果默认返回false,会报出各种用户相关的异常
1  | 
  | 
3.JwtUserDetailsServiceImpl
重写security的UserDaiService的loadByusername方法,实现自定义的权限验证
1  | 
  | 
3.3 token生成方法
1  | 
  | 
3.4 token校验过滤器
每次请求的时候都会被该过滤器过滤拦截。主要是校验token的有效性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
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    
    private JwtUserDetailsServiceImpl userDetailsService;
    private JwtTokenUtil jwtTokenUtil;
    public JwtAuthenticationTokenFilter(JwtTokenUtil jwtTokenUtil) {
        this.jwtTokenUtil = jwtTokenUtil;
    }
    /**
     * 每个请求都被拦截
     * Same contract as for {@code doFilter}, but guaranteed to be
     * just invoked once per request within a single request thread.
     * See {@link #shouldNotFilterAsyncDispatch()} for details.
     * <p>Provides HttpServletRequest and HttpServletResponse arguments instead of the
     * default ServletRequest and ServletResponse ones.
     *
     * @param request
     * @param response
     * @param filterChain
     */
    
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String authHeader = request.getHeader("Authorization");
        String tokenHead = "Bearer ";
        if (authHeader != null && authHeader.startsWith(tokenHead)) {
            String authToken = authHeader.substring(tokenHead.length());
            String username = jwtTokenUtil.getUsernameFromToken(authToken);
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                //返回jwtUser
                UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
                if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    //将该用户的权限信息存放到threadlocal中
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }
        }
        filterChain.doFilter(request, response);
    }
}
3.4 webSecurity配置
1  | 
  | 
至此,相关的配置就配置完了。在登录操作的时候需要注意一下:
用户信息的验证全部交给spring security来操作,代码如下:
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 /**
* 登录操作,返回token
* @param userName
* @param password
* @return
* @throws Exception
*/
public String login(String userName, String password) throws Exception {
UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(userName, password);
Authentication authentication = authenticationManager.authenticate(upToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetails userDetails = userDetailsService.loadUserByUsername(userName);
return jwtTokenUtil.generateToken(userDetails);
}
3.4 用户验证流程
1  | UsernamePasswordAuthenticationToken  |