参考原文Spring Boot Security + JWT Hello World Example: https://www.javainuse.com/spring/boot-jwt
自我总结:
① 客户端发送POST请求,在POSTman的requestBody里边以json字符串作为参数发送请求,参数有username和password
② 在JwtAuthenticationController里边,这是用来验证用户名密码的controller,请求参数是 @RequestBody JwtRequest authenticationRequest,在第①步骤发送的json字符串被转化称对象,传进authenticationRequest,因为JwtRequest这个model已经实现了Serializable接口,所以发送post请求的json字符串可以转化为对象类型
③ 接收到JwtRequet对象(自定义model类)jwtRequest以后,通过 jwtRequest.getUsername() 和 jwtRequest.getPassword() 方法获取用户名和密码,把这些用户名和密码传入AuthenticationManager接口的 authenticate(new UsernamePasswordAuthenticationToken( jwtRequest.getUsername() , jwtRequest.getPassword() )) 方法,这个AuthenticationManager接口的authenticate方法的作用是对用户的未授信凭据进行认证,认证通过则返回授信状态的凭据
④ 通过 调用 userDetailsService.loadUserByUsername(jwtRequest.getUsername()); 返回一个User类型(springsecurity源码类), 将这个返回值赋值给UserDetails接口的对象 userDetails 。userDetails里面可以获取用户详细信息。代码:
final UserDetails userDetails = userDetailsService.loadUserByUsername(jwtRequest.getUsername());
⑤ 通过使用 jwtTokenUtil工具类调用generateToken方法,传入userDetails对象,生成token字符串,最后返回一个token字符串。代码:
final String token = jwtTokenUtil.generateToken(userDetails);
⑥ 生成token字符串以后,在请求头带着token去发送get请求以访问目标业务,那么这个token是否合法呢?怎么验证token是否合法呢,那么首先要通过JwtRequestFilter过滤器
⑦ 在JwtRequestFilter过滤器里边,JwtRequestFilter继承了OncePerRequestFilter,实现了doFilterInternal方法,方法里面有3个参数,分别是
HttpServletRequest request, HttpServletResponse response, FilterChain chain
那么我们带着token发送get请求去执行业务的时候,通过这三个参数里边的HttpServletRequest request 去获取请求头信息,即:
final String requestTokenHeader = request.getHeader("Authorization");
(1)判断1:首先判断 requestTokenHeader (请求头信息,其实就是token字符串有关信息)是否非空,而且判断requestTokenHeader是否以字符串 "Bearer " 开头,如果满足条件
那么去掉前面7个字符串,得到字符串 jwtToken (真正的token),通过 jwtToken工具类调用 jwtTokenUtil.getUsernameFromToken(jwtToken); 方法,从token里面获取username
(2)判断2:再次判断 username 是否非空, SecurityContextHolder.getContext().getAuthentication() 是否为空,如果满足条件
那么通过 this.jwtUserDetailsService.loadUserByUsername(username) 方法返回User类型的对象,赋值给UserDetails接口对象,即通过username去获取用户信息详情,可以通过userDetails对象取获取用户名、密码、授予哪些权限,代码:
System.out.println("userDetails的密码:"+userDetails.getPassword());
System.out.println("userDetails的用户名:"+userDetails.getUsername());
//获取userDetails的授权有哪些,返回的是一个数组
System.out.println("userDetails的授权:"+userDetails.getAuthorities());
(3)判断2的子判断:判断 jwtTokenUtil.validateToken(jwtToken, userDetails) 是否返回true,即通过token和userDetails对象来验证其合法性,如果合法,执行以下代码通过验证:
UsernamePasswordAuthenticationToken uPAT = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities()
);
uPAT.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(uPAT);
最后 chain.doFilter(request, response);
⑧ 允许访问HelloWorldController的业务