这两天做 SpringBoot+Spring Security和JWT的集成实现登陆授权认证 ,找了很多文章,看了很多的博客都不敬人意,终于功夫不负有心人,总算是把这个授权认证做好了,特此记录一下 。具体的原理我这就不做过多阐述,感兴趣的人可以自己去看相关的文章。下面直接上代码:
- 导入对应依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
- 添加 token 工具类
/**
* @author
* @version 1.0.0
* @ClassName JWTUtil.java
* @Description JWTUtil
* @createTime 2022年01月09日 21:29:00
*/
@Component
public class JWTUtil implements Serializable {
private static final long serialVersionUID = -916592859157433572L;
private static final long JWT_TOKEN_VALIDITY = 5 * 60 * 60;
@Value("${jwt.secret}")
private String secretKey;
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
private <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
private Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userDetails.getUsername());
}
private String doGenerateToken(Map<String, Object> claims, String subject) {
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis())).setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000)).signWith(SignatureAlgorithm.HS512, secretKey).compact();
}
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
public static void main(String[] args) {
}
}
- 添加过滤器(实现登陆的认证和授权)
@Component
public class JwtFilter extends OncePerRequestFilter {
@Autowired
private JWTUtil jwtUtil;
@Autowired
UserDetailsServiceIml userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String authorization = request.getHeader("Authorization");
String token = null;
String username = null;
//获取token
if (null != authorization && authorization.startsWith("Bearer ")) {
token = authorization.substring(7);
username = jwtUtil.getUsernameFromToken(token);
}
// 认证授权
if (null != username && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsServiceIml.loadUserByUsername(username);
if (jwtUtil.validateToken(token, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
else {
try {
throw new ValidationException("token 过期");
} catch (ValidationException e) {
e.printStackTrace();
}
}
}
filterChain.doFilter(request, response);
}
}
- 登陆实现
@Service
public class LoginUserServiceIml implements LoginUserService {
@Autowired
JWTUtil jwtUtil;
@Autowired
UserDetailsServiceIml userDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Override
public String login(LoginUser loginUser) throws Exception {
try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginUser.getUsername(),
loginUser.getPassword()
)
);
} catch (BadCredentialsException e) {
throw new Exception("用户或密码错误", e);
}
UserDetails userDetails = userDetailsService.loadUserByUsername(loginUser.getUsername());
StringBuilder stringBuilder = new StringBuilder("Bearer ");
stringBuilder.append(jwtUtil.generateToken(userDetails));
return stringBuilder.toString();
}
@Override
public boolean register(SysUser sysUser) {
return false;
}
}
- WebSecurityConfigurer 配置
@Override
protected void configure(HttpSecurity http) throws Exception {
//跨域放行
http.authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll();
//停掉 session
http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests()
.antMatchers("/sys/api/**").permitAll();
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
至此即完成jwt的相关配置