WebAuthn 是一种用于进行强身份验证的开放标准,可以用于替代传统的用户名密码登录方式。如果您想要写一个使用 WebAuthn 进行登录验证的小项目,需要分别实现前端和后端的代码。
以下是一个使用 WebAuthn 进行登录验证的示例项目,包括前端和后端的代码实现,供您参考:
在前端实现中,我们需要使用 navigator.credentials.create() 和 navigator.credentials.get() 方法来创建和获取 WebAuthn 凭证,并将凭证信息发送到后端进行验证。以下是一个简单的示例代码:
// 创建 WebAuthn 凭证
async function createCredential() {
const publicKey = await fetch('/api/webauthn/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
}).then(response => response.json());
const credential = await navigator.credentials.create({ publicKey });
await fetch('/api/webauthn/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(credential),
});
}
// 获取 WebAuthn 凭证
async function getCredential() {
const publicKey = await fetch('/api/webauthn/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
}).then(response => response.json());
const credential = await navigator.credentials.get({ publicKey });
await fetch('/api/webauthn/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(credential),
});
}
在上述代码中,我们分别定义了 createCredential()
和 getCredential()
两个函数,用于创建和获取 WebAuthn 凭证。在这两个函数中,我们使用 fetch() 方法向后端发送请求,获取 WebAuthn 的公钥,并将凭证信息发送到后端进行验证。
在后端实现中,我们需要使用 WebAuthn 库(例如 webauthn4j
)来对 WebAuthn 凭证进行验证。以下是一个简单的 Java 示例代码:
// 注册 WebAuthn 凭证
@PostMapping("/api/webauthn/register")
public PublicKeyCredentialCreationOptions register() {
// 生成随机的用户 ID 和挑战值
byte[] userId = UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8);
byte[] challenge = getRandomBytes(32);
// 构造 WebAuthn 公钥参数
PublicKeyCredentialCreationOptions publicKeyCredentialCreationOptions = new PublicKeyCredentialCreationOptions();
publicKeyCredentialCreationOptions.setRp(new PublicKeyCredentialRpEntity("example.com", "Example"));
publicKeyCredentialCreationOptions.setUser(new PublicKeyCredentialUserEntity(userId, "example@example.com", "Example"));
publicKeyCredentialCreationOptions.setChallenge(challenge);
publicKeyCredentialCreationOptions.setPubKeyCredParams(Collections.singletonList(new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, ECNamedCurveTable.getParameterSpec("P-256"))));
publicKeyCredentialCreationOptions.setTimeout(60000);
publicKeyCredentialCreationOptions.setExcludeCredentials(Collections.emptyList());
publicKeyCredentialCreationOptions.setAuthenticatorSelection(new AuthenticatorSelectionCriteria(null, AuthenticatorAttachment.PLATFORM, null, true));
publicKeyCredentialCreationOptions.setAttestation(AttestationConveyancePreference.DIRECT);
return publicKeyCredentialCreationOptions;
}
// 验证 WebAuthn 凭证
@PostMapping("/api/webauthn/login")
public void login(@RequestBody PublicKeyCredential<AuthenticatorAssertionResponse, ClientAssertionExtensionOutputs> credential) {
// 获取用户 ID 和挑战值
byte[] userId = credential.getResponse().getUserHandle();
byte[] challenge = getChallenge();
// 构造 WebAuthn 验证参数
PublicKeyCredentialRequestOptions publicKeyCredentialRequestOptions = new PublicKeyCredentialRequestOptions();
publicKeyCredentialRequestOptions.setChallenge(challenge);
publicKeyCredentialRequestOptions.setRpId("example.com");
publicKeyCredentialRequestOptions.setAllowCredentials(Collections.singletonList(new PublicKeyCredentialDescriptor(PublicKeyCredentialType.PUBLIC_KEY, credential.getId().getId(), null)));
publicKeyCredentialRequestOptions.setTimeout(60000);
// 调用 WebAuthn 库进行验证
WebAuthnManager webAuthnManager = WebAuthnManager.builder()
.rpId("example.com")
.credentialRepository(credentialRepository)
.metadataService(metadataService)
.build();
RegistrationResult registrationResult = webAuthnManager.finishRegistration(FinishRegistrationOptions.builder()
.request(credential)
.response(credential.getResponse())
.build());
}
在上述代码中,我们使用 Spring Boot 作为后端框架,并使用 webauthn4j
库来进行 WebAuthn 凭证的验证。在 /api/webauthn/register
接口中,我们生成了一个随机的用户 ID 和挑战值,并使用 PublicKeyCredentialCreationOptions
构造函数创建 WebAuthn 公钥参数。在 /api/webauthn/login
接口中,我们获取了用户 ID 和挑战值,并使用 PublicKeyCredentialRequestOptions
构造函数创建 WebAuthn 验证参数。然后,我们使用 WebAuthnManager
对象进行 WebAuthn 凭证的验证。
以上代码只是一个示例,实际的实现可能会因为具体的业务需求而有所不同。如果您对 WebAuthn 的使用还不够熟悉,建议先阅读相关的文档和教程,了解其基本原理和使用方法。