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 |