Spring Security WebAuthn实现Passkey遇400错误,求排查配置遗漏
我需要在应用中实现Passkey的注册与认证功能。查阅WebAuthn4J文档后得知官方推荐用Spring Security简化开发流程,参考Spring Security官方Passkey文档配置后,添加了相关依赖并在SecurityFilterChain中配置了webauthn(...),但向/webauthn/register/options接口发送POST请求获取challenge时,服务器仅返回400状态码和空响应体。我对WebAuthn概念有一定了解,但对Spring Security版本的WebAuthn使用方式存疑,核心疑问是:是否遗漏了必要配置项?
配置信息
build.gradle(片段)
dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation "org.springframework.boot:spring-boot-starter-security" implementation "org.springframework.security:spring-security-config" implementation "org.springframework.security:spring-security-web" implementation "com.webauthn4j:webauthn4j-core:0.28.3.RELEASE" }
WebSecurityConfig.java
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.configurers.AbstractHttpConfigurer; import org.springframework.security.web.SecurityFilterChain; @Configuration public class WebSecurityConfig { @Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests((authorize) -> authorize.anyRequest().permitAll()) .webAuthn((webAuthn) -> webAuthn .rpName("SAVIN") .rpId("http://localhost") .allowedOrigins("http://localhost") ); return http.build(); } }
从你的配置和问题来看,主要有几个关键问题导致400错误:
依赖配置错误
你只引入了webauthn4j-core,但Spring Security整合WebAuthn需要专门的starter依赖,无需单独引入webauthn4j-core(starter已包含兼容版本)。修改build.gradle,替换原webauthn4j依赖为:implementation "org.springframework.security:spring-security-webauthn"注意:确保Spring Boot版本在3.1以上、Spring Security版本在6.1以上,这两个版本才内置了WebAuthn支持。
rpId格式错误
WebAuthn规范要求rpId是纯域名,不能带协议(http://)或端口。把配置中的rpId("http://localhost")改成rpId("localhost")即可。请求缺少必要参数
/webauthn/register/options接口需要接收包含用户标识的请求体,空请求体会直接返回400。发送POST请求时,需要在请求体中传入username或userHandle,示例请求体:{ "username": "your-test-username" }额外注意点
如果你的应用运行在非默认端口(比如8080),需要在allowedOrigins中加上端口,比如allowedOrigins("http://localhost:8080"),同时rpId保持localhost即可。
内容的提问来源于stack exchange,提问作者EyedPeas

