跳到主要内容

Spring Cloud Security 如何实现JWT生成 ?

参考答案:

在Spring Cloud中,我们通常使用Spring Security来管理安全性,并通过JWT(JSON Web Tokens)来实现无状态的认证机制。为了生成JWT,我们可以使用第三方库,如jjwt。以下是如何在Spring Cloud Security项目中集成JWT生成和验证的基本步骤:

  1. 添加依赖

首先,在pom.xml中添加必要的依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version> <!-- 请检查最新版本 -->
</dependency>
  1. 配置Spring Security

接下来,配置Spring Security以使用JWT。

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtRequestFilter jwtRequestFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
            .antMatchers("/login").permitAll()
            .anyRequest().authenticated()
            .and()
            .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint);

        http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // ... 其他必要的配置
}
  1. 创建JWT工具类

创建一个工具类来处理JWT的生成和验证。

@Component
public class JwtUtil {

    private static final long EXPIRATION_TIME = 86400000; // 1 day in milliseconds
    private static final String SECRET = "your-secret-key"; // Change this to a secure key

    public String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(((User) userDetails).getUsername())
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .compact();
    }

    public String getUsernameFromJWT(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(SECRET)
                .parseClaimsJws(token)
                .getBody();

        return claims.getSubject();
    }

    public boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
            return true;
        } catch (SignatureException ex) {
            // JWT signature does not match
        } catch (MalformedJwtException ex) {
            // JWT string is malformed
        } catch (ExpiredJwtException ex) {
            // JWT has expired
        } catch (UnsupportedJwtException ex) {
            // JWT is of an unsupported type
        } catch (IllegalArgumentException ex) {
            // JWT string is empty
        }
        return false;
    }
}
  1. 创建JWT认证入口点和过滤器

JWT认证入口点用于处理未授权的请求,而JWT请求过滤器用于验证每个请求的JWT。

@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException authException) throws IOException, ServletException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
    }
}

@Component
public class JwtRequestFilter extends OncePerRequestFilter {

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)