如何为Spring Security 6.4.4 WebAuthn(Passkey)认证自定义onAuthenticationSuccess?
解决方案
要实现WebAuthn认证成功后在响应头添加JWT Token,你可以通过自定义认证成功处理器并替换WebAuthnAuthenticationFilter的默认处理器来实现,具体步骤如下:
1. 自定义AuthenticationSuccessHandler
你可以选择直接实现AuthenticationSuccessHandler接口,或者继承默认的HttpMessageConverterAuthenticationSuccessHandler以保留原有响应逻辑同时添加自定义操作。
方式一:完全自定义处理器
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import java.io.IOException; public class WebAuthnJwtSuccessHandler implements AuthenticationSuccessHandler { private final JwtTokenProvider jwtTokenProvider; // 注入JWT生成工具类 public WebAuthnJwtSuccessHandler(JwtTokenProvider jwtTokenProvider) { this.jwtTokenProvider = jwtTokenProvider; } @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { // 生成JWT Token String jwtToken = jwtTokenProvider.generateToken(authentication); // 将Token写入响应头 response.setHeader("Authorization", "Bearer " + jwtToken); // 设置响应状态码为200 response.setStatus(HttpServletResponse.SC_OK); } }
方式二:继承默认处理器保留原有响应
如果你希望保留默认处理器返回认证信息的逻辑,同时添加JWT头,可以继承HttpMessageConverterAuthenticationSuccessHandler:
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.HttpMessageConverterAuthenticationSuccessHandler; import java.io.IOException; public class CustomWebAuthnSuccessHandler extends HttpMessageConverterAuthenticationSuccessHandler { private final JwtTokenProvider jwtTokenProvider; public CustomWebAuthnSuccessHandler(JwtTokenProvider jwtTokenProvider) { this.jwtTokenProvider = jwtTokenProvider; } @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { // 先执行默认逻辑,返回认证信息 super.onAuthenticationSuccess(request, response, authentication); // 添加JWT到响应头 String jwtToken = jwtTokenProvider.generateToken(authentication); response.setHeader("Authorization", "Bearer " + jwtToken); } }
2. 实现JWT生成工具类
这里以JJWT库为例,实现简单的JWT生成逻辑:
import io.jsonwebtoken.Jwts; import io.jsonwebtoken.security.Keys; import org.springframework.security.core.Authentication; import java.security.Key; import java.util.Date; public class JwtTokenProvider { // 生成签名密钥(生产环境建议从配置文件读取) private final Key secretKey = Keys.secretKeyFor(io.jsonwebtoken.SignatureAlgorithm.HS256); // Token有效期(1小时) private final long validityInMilliseconds = 3600000; public String generateToken(Authentication authentication) { Date now = new Date(); Date validity = new Date(now.getTime() + validityInMilliseconds); return Jwts.builder() .setSubject(authentication.getName()) // 设置用户名作为Token主题 .setIssuedAt(now) // 签发时间 .setExpiration(validity) // 过期时间 .signWith(secretKey) // 签名 .compact(); } }
3. 更新SecurityFilterChain配置
在WebAuthn配置中指定自定义的认证成功处理器:
import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.web.SecurityFilterChain; import static org.springframework.security.config.Customizer.withDefaults; @Bean SecurityFilterChain filterChain(HttpSecurity http, JwtTokenProvider jwtTokenProvider) throws Exception { http .csrf(AbstractHttpConfigurer::disable) // 根据实际需求配置CSRF // ...其他配置(如权限规则等) .formLogin(withDefaults()) .webAuthn((webAuthn) -> webAuthn .rpName("Spring Security Relying Party") .rpId("localhost") .allowedOrigins("http://localhost:9000") // 指定自定义成功处理器 .authenticationSuccessHandler(new WebAuthnJwtSuccessHandler(jwtTokenProvider)) // 如果用继承默认处理器的方式,替换为: // .authenticationSuccessHandler(new CustomWebAuthnSuccessHandler(jwtTokenProvider)) ); return http.build(); }
4. 添加JJWT依赖(如果使用上述JWT工具类)
在build.gradle中添加JJWT相关依赖:
dependencies { implementation "org.springframework.security:spring-security-web" implementation "com.webauthn4j:webauthn4j-core:0.28.6.RELEASE" // JJWT依赖 implementation "io.jsonwebtoken:jjwt-api:0.11.5" runtimeOnly "io.jsonwebtoken:jjwt-impl:0.11.5" runtimeOnly "io.jsonwebtoken:jjwt-jackson:0.11.5" }
内容的提问来源于stack exchange,提问作者Florian
相关产品推荐
相关产品推荐

