You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 13:26:21