user("web")->name, $request->user("web")->id, $request->user("web")->name, ); $challenge = random_bytes(16); $request->session()->put("webauthn_register_challenge", $challenge); return WebAuthnService::createRequestOptions($userEntity, $challenge); } public function login_options(Request $request): PublicKeyCredentialRequestOptions { $challenge = random_bytes(32); $request->session()->put("webauthn_login_challenge", $challenge); $publicKeyCredentialRequestOptions = new PublicKeyCredentialRequestOptions( $challenge ); $publicKeyCredentialRequestOptions->setUserVerification( PublicKeyCredentialRequestOptions::USER_VERIFICATION_REQUIREMENT_REQUIRED ); $publicKeyCredentialRequestOptions->allowCredentials([]); return $publicKeyCredentialRequestOptions; } public function register_validate(Request $request) { if (!$request->session()->has("webauthn_register_challenge")) { return new Response([ "success" => false, "code" => 403, "message" => "重放攻击可能?无对应验证请求" ], 403); } $publicKeyCredential = WebAuthnService::getPublicKeyCredentialLoader()->loadArray($request->json()->all()); $authenticatorAttestationResponse = $publicKeyCredential->getResponse(); if (!$authenticatorAttestationResponse instanceof AuthenticatorAttestationResponse) { //e.g. process here with a redirection to the public key creation page. return new Response([ "success" => false, "code" => 400, "message" => "接口调用错误?无法验证请求" ], 400); } $userEntity = new PublicKeyCredentialUserEntity( $request->user("web")->name, $request->user("web")->id, $request->user("web")->name, ); $challenge = $request->session()->remove("webauthn_register_challenge"); $publicKeyCredentialCreationOptions = WebAuthnService::createRequestOptions($userEntity, $challenge); try { $publicKeyCredentialSource = WebAuthnService::getAuthenticatorAttestationResponseValidator()->check( $authenticatorAttestationResponse, $publicKeyCredentialCreationOptions, ServerRequest::fromGlobals(), ["localhost"] ); } catch (\Throwable $e) { return new Response([ "success" => false, "code" => 500, "message" => "服务器异常", "exception" => $e->getMessage() ], 500); } WebAuthnService::getPublicKeyCredentialSourceRepository()->saveCredentialSource($publicKeyCredentialSource); return $publicKeyCredentialSource; } public function login_validate(Request $request) { if (!$request->session()->has("webauthn_login_challenge")) { return new Response([ "success" => false, "code" => 403, "message" => "重放攻击可能?无对应验证请求" ], 403); } $publicKeyCredentialRequestOptions = new PublicKeyCredentialRequestOptions( $request->session()->remove("webauthn_login_challenge") ); $publicKeyCredential = WebAuthnService::getPublicKeyCredentialLoader()->loadArray($request->json()->all()); $authenticatorAssertionResponse = $publicKeyCredential->getResponse(); if (!$authenticatorAssertionResponse instanceof AuthenticatorAssertionResponse) { //e.g. process here with a redirection to the public key login/MFA page. return new Response([ "success" => false, "code" => 400, "message" => "接口调用错误?无法验证请求" ], 400); } try { $publicKeyCredentialSource = WebAuthnService::getAuthenticatorAssertionResponseValidator()->check( $publicKeyCredential->getRawId(), $authenticatorAssertionResponse, $publicKeyCredentialRequestOptions, ServerRequest::fromGlobals(), $authenticatorAssertionResponse->getUserHandle(), ["localhost"] ); } catch (\Throwable $e) { return new Response([ "success" => false, "code" => 500, "message" => "服务器异常", "exception" => $e->getMessage() ], 500); } Auth::loginUsingId($publicKeyCredentialSource->getUserHandle()); return [ "success" => true, "code" => 0, "message" => "登录成功", "userId" => $publicKeyCredentialSource->getUserHandle() ]; } }