配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。包括用户认证和用户授权,在使用Session的认证中,security取出session中的信息进行验证。使用了JWT,禁用session,需要在security之前加上filter,在filter中验证token然后把用户信息和session一样填入SecurityContext中。
禁用session
// 基于token,所以不需要session
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
在securityconfig中加入filter
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
filter中验证token
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Autowired
private UserService userDetailsService;
@Autowired
private JWTUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
String token = request.getHeader(jwtTokenUtil.getHeader());
String username = jwtTokenUtil.getUsernameFromToken(token);
logger.info(String.format("Checking authentication for user %s.", username));
if (!StringUtils.isEmpty(token)) {
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null){
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(token, userDetails)){
// 将用户信息存入 authentication,方便后续校验
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// 将 authentication 存入 ThreadLocal,方便后续获取用户信息
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
chain.doFilter(request, response);
}
}
使用JWT的好处:
1. 可扩展性好
应用程序分布式部署的情况下,session需要做多机数据共享,通常可以存在数据库或者redis里面。而jwt不需要。
2. 无状态,降低耦合度
jwt不在服务端存储任何状态。RESTful API的原则之一是无状态,发出请求时,总会返回带有参数的响应,不会产生附加影响。用户的认证状态引入这种附加影响,这破坏了这一原则。另外jwt的载荷中可以存储一些常用信息,用于交换信息,有效地使用 JWT,可以降低服务器查询数据库的次数。