• SpringSecurity整合JWT


    Spring Security是一个强大的安全性框架,它提供了许多强大的功能来保护应用程序,而JWT(JSON Web Token)是一种用于在网络环境中传递声明的开放标准。

    整合Spring Security和JWT,可以使我们的应用程序更加安全和高效。下面是整合步骤:

    1. 添加Spring Security和JWT的依赖:
    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-security</artifactId>
    4. </dependency>
    5. <dependency>
    6. <groupId>io.jsonwebtoken</groupId>
    7. <artifactId>jjwt</artifactId>
    8. <version>0.9.1</version>
    9. </dependency>

    1. 配置Spring Security

    在Spring的配置类中,我们需要设置一些安全配置,包括:

    • 配置安全规则
    • 配置JWT过滤器
    • 配置认证管理器
    1. @Configuration
    2. @EnableWebSecurity
    3. public class SecurityConfig extends WebSecurityConfigurerAdapter {
    4. private static final String[] AUTH_WHITELIST = {
    5. "/swagger-resources/**",
    6. "/swagger-ui.html",
    7. "/v2/api-docs",
    8. "/webjars/**"
    9. };
    10. @Autowired
    11. private JwtFilter jwtFilter;
    12. @Autowired
    13. private UserDetailsService userDetailsService;
    14. @Override
    15. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    16. auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    17. }
    18. @Bean
    19. public PasswordEncoder passwordEncoder() {
    20. return new BCryptPasswordEncoder();
    21. }
    22. @Bean
    23. @Override
    24. public AuthenticationManager authenticationManagerBean() throws Exception {
    25. return super.authenticationManagerBean();
    26. }
    27. @Override
    28. protected void configure(HttpSecurity http) throws Exception {
    29. http
    30. .cors().and().csrf().disable()
    31. .authorizeRequests()
    32. .antMatchers(AUTH_WHITELIST).permitAll()
    33. .antMatchers("/api/authenticate").permitAll()
    34. .anyRequest().authenticated()
    35. .and()
    36. .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    37. http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
    38. }
    39. @Bean(BeanIds.AUTHENTICATION_MANAGER)
    40. public AuthenticationManager authenticationManagerBean() throws Exception {
    41. return super.authenticationManagerBean();
    42. }
    43. }

    1. 配置JWT
    1. @Configuration
    2. public class JwtConfig {
    3. @Value("${jwt.secret}")
    4. private String secret;
    5. @Value("${jwt.expiration}")
    6. private long expiration;
    7. @Bean
    8. public JwtEncoder jwtEncoder() {
    9. return new JwtEncoder(secret, expiration);
    10. }
    11. @Bean
    12. public JwtDecoder jwtDecoder() {
    13. return new JwtDecoder(secret);
    14. }
    15. }

    1. 实现自定义UserDetailsService

    我们需要提供一个实现了UserDetailsService接口的自定义类,用于从数据库中获取用户信息。

    1. @Service
    2. public class UserDetailsServiceImpl implements UserDetailsService {
    3. @Autowired
    4. private UserRepository userRepository;
    5. @Override
    6. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    7. User user = userRepository.findByUsername(username);
    8. if (user == null) {
    9. throw new UsernameNotFoundException("User not found with username: " + username);
    10. }
    11. return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
    12. Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));
    13. }
    14. }

    1. 实现JwtEncoder和JwtDecoder

    我们需要提供一个JwtEncoder和JwtDecoder类,用于创建和验证JWT。

    1. public class JwtEncoder {
    2. private final String secret;
    3. private final long expiration;
    4. public JwtEncoder(String secret, long expiration) {
    5. this.secret = secret;
    6. this.expiration = expiration;
    7. }
    8. public String createToken(UserDetails userDetails) {
    9. Map<String, Object> claims = new HashMap<>();
    10. claims.put("sub", userDetails.getUsername());
    11. claims.put("iat", new Date());
    12. claims.put("exp", new Date(System.currentTimeMillis() + expiration));
    13. return Jwts.builder()
    14. .setClaims(claims)
    15. .signWith(SignatureAlgorithm.HS512, secret)
    16. .compact();
    17. }
    18. }
    19. public class JwtDecoder {
    20. private final String secret;
    21. public JwtDecoder(String secret) {
    22. this.secret = secret;
    23. }
    24. public String getUsernameFromToken(String token) {
    25. return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getSubject();
    26. }
    27. public boolean validateToken(String token) {
    28. try {
    29. Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
    30. return true;
    31. } catch (SignatureException e) {
    32. LOGGER.error("Invalid JWT signature - {}", e.getMessage());
    33. } catch (MalformedJwtException e) {
    34. LOGGER.error("Invalid JWT token - {}", e.getMessage());
    35. } catch (ExpiredJwtException e) {
    36. LOGGER.error("Expired JWT token - {}", e.getMessage());
    37. } catch (UnsupportedJwtException e) {
    38. LOGGER.error("Unsupported JWT token - {}", e.getMessage());
    39. } catch (IllegalArgumentException e) {
    40. LOGGER.error("JWT claims string is empty - {}", e.getMessage());
    41. }
    42. return false;
    43. }
    44. }

    1. 实现JWT过滤器

    我们需要提供一个JwtFilter类,用于过滤JWT。

    1. @Component
    2. public class JwtFilter extends OncePerRequestFilter {
    3. @Autowired
    4. private JwtDecoder jwtDecoder;
    5. @Autowired
    6. private UserDetailsService userDetailsService;
    7. @Override
    8. protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
    9. String header = request.getHeader("Authorization");
    10. if (StringUtils.isBlank(header) || !header.startsWith("Bearer ")) {
    11. chain.doFilter(request, response);
    12. return;
    13. }
    14. String token = header.replace("Bearer ", "");
    15. if (jwtDecoder.validateToken(token)) {
    16. String username = jwtDecoder.getUsernameFromToken(token);
    17. UserDetails userDetails = userDetailsService.loadUserByUsername(username);
    18. UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
    19. authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
    20. SecurityContextHolder.getContext().setAuthentication(authentication);
    21. }
    22. chain.doFilter(request, response);
    23. }
    24. }

    至此,我们已经成功地整合了Spring Security和JWT。

  • 相关阅读:
    WebAPI中使用WebService后发布注意要点
    分布式缓存-Redis分片集群
    linux高性能服务器
    1-3 docker 安装 prometheus
    2022 OpenCV AI 竞赛来啦!详细介绍Spatial AI赛道!
    【云原生】-国产开源数据库openGauss容器部署
    .NET 中 GC 的模式与风格
    【c++百日刷题计划】 ———— DAY16,刷题百天,养成刷题好习惯
    电子学会2021年6月青少年软件编程(图形化)等级考试试卷(四级)答案解析
    H5 手机键盘兼容
  • 原文地址:https://blog.csdn.net/NanCheng_666/article/details/134272592