Spring Boot 3:如何用RSA256公钥验证JWT并设置Authentication?
一、用现有公钥验证JWT的实现
你已经通过代码拿到了RSAPublicKey,无需手动解析JWT签名,直接借助Spring Security提供的JwtDecoder就能完成验证:
构建JwtDecoder实例
用Spring默认的NimbusJwtDecoder结合你的公钥创建解码器:import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; JwtDecoder jwtDecoder = NimbusJwtDecoder.withPublicKey(publicKey).build();在自定义Filter中完成验证与Authentication设置
在你的JwtTokenFilter里,提取Bearer Token后用解码器验证,再生成JwtAuthenticationToken放入SecurityContext:import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.oauth2.jwt.JwtAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.filter.OncePerRequestFilter; public class JwtTokenFilter extends OncePerRequestFilter { private final JwtDecoder jwtDecoder; public JwtTokenFilter(JwtDecoder jwtDecoder) { this.jwtDecoder = jwtDecoder; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String authHeader = request.getHeader("Authorization"); if (authHeader != null && authHeader.startsWith("Bearer ")) { String token = authHeader.substring(7); try { // 验证并解析JWT Jwt jwt = jwtDecoder.decode(token); // 生成Authentication对象 Authentication auth = new JwtAuthenticationToken(jwt, null); // 存入SecurityContext SecurityContextHolder.getContext().setAuthentication(auth); } catch (Exception e) { // 验证失败直接返回401 response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "无效的JWT Token"); return; } } filterChain.doFilter(request, response); } }
二、Spring内置的简化方案(强烈推荐)
Spring Security 6+的OAuth2 Resource Server模块已经封装了全套JWT验证逻辑,无需手动编写Filter,几步就能完成配置:
添加依赖
Maven项目在pom.xml中添加:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-resource-server</artifactId> </dependency>自动加载公钥并配置JwtDecoder
完全不用手动处理PEM格式的公钥,Spring支持直接从配置文件指定公钥路径:
在application.yml中添加:spring: security: oauth2: resourceserver: jwt: public-key-location: classpath:jwtPublicKey.pub这样Spring会自动完成公钥读取、格式解析,并创建
JwtDecoder实例。配置SecurityFilterChain
只需开启OAuth2 Resource Server的JWT支持,Spring会自动处理Bearer Token的验证和Authentication注入:import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .oauth2ResourceServer(oauth2 -> oauth2.jwt()); return http.build(); } }如果需要自定义JWT到Authentication的转换逻辑(比如从claims中提取权限),可以扩展
jwtAuthenticationConverter:.oauth2ResourceServer(oauth2 -> oauth2 .jwt(jwt -> jwt .jwtAuthenticationConverter(jwt -> { // 根据JWT的claims自定义权限集合 Collection<GrantedAuthority> authorities = ...; return new JwtAuthenticationToken(jwt, authorities); }) ) )
这套方案会自动拦截请求、提取Bearer Token、验证签名,验证通过后自动将JwtAuthenticationToken放入SecurityContext,比手动实现简洁高效得多。
内容的提问来源于stack exchange,提问作者nonNumericalFloat

