WebAuthn 無密碼登入
Doggy 基於 web-auth/webauthn-symfony-bundle 實作 WebAuthn 標準認證,支援指紋、臉部辨識和安全金鑰登入。
概述
WebAuthn 憑證儲存在 src/Entity/Security/WebauthnCredential.php(表 webauthn_credentials),關聯至 App\Entity\Organization\Employee(使用者實體)。
憑證存放庫實作 PublicKeyCredentialSourceRepositoryInterface,支援儲存與查詢 WebAuthn 憑證。
設定
yaml
# config/packages/webauthn.yaml
webauthn:
credential_repository: 'App\Repository\Security\WebauthnCredentialRepository'
user_repository: 'App\Repository\Organization\EmployeeRepository'
creation_profiles:
default:
rp:
name: '%env(RELYING_PARTY_NAME)%'
id: '%env(RELYING_PARTY_ID)%'
public_key_credential_parameters:
- -7 # ES256
- -257 # RS256
authenticator_selection_criteria:
resident_key: required
user_verification: required
request_profiles:
default:
rp_id: '%env(RELYING_PARTY_ID)%'
user_verification: required
allowed_origins: ['http://localhost:8000']安全防火牆設定
yaml
# config/packages/security.yaml
security:
firewalls:
main:
custom_authenticator: App\Security\AppCustomAuthenticator
webauthn:
success_handler: App\Security\WebauthnSuccessHandler
authentication:
enabled: true
routes:
options_path: '/login/webauthn/options'
result_path: '/login/webauthn/result'憑證管理
php
// src/Entity/Security/WebauthnCredential.php
class WebauthnCredential
{
private string $publicKeyCredentialId;
private string $type; // 'public-key'
private array $transports; // ['usb', 'nfc', 'internal']
private string $attestationType;
private string $credentialPublicKey;
private string $userHandle; // Employee ID
private int $counter;
private ?string $deviceName; // 如 "Chrome on Mac"
#[ORM\ManyToOne(targetEntity: Employee::class, inversedBy: 'passkeys')]
private ?Employee $employee = null;
}登入流程
註冊 Passkey
- 使用者登入後進入安全設定(
/user/webauthn/register/options) - 瀏覽器呼叫 WebAuthn API 建立憑證
- 結果提交至
/user/webauthn/register/result - 公鑰憑證儲存至
webauthn_credentials表
無密碼登入
- 輸入使用者名稱,點擊「Passkey 登入」
- POST 到
/login/webauthn/options取得挑戰 - 瀏覽器呼叫 WebAuthn API 簽章
- 結果提交至
/login/webauthn/result WebauthnSuccessHandler處理登入成功(記錄裝置、更新時間)
成功處理器
App\Security\WebauthnSuccessHandler 在登入成功後:
- 更新憑證最後使用時間
- 自動辨識裝置名稱(User-Agent 解析)
- 檢查是否為首次登入,引導密碼修改
- 支援密碼重設流程
WebAuthn 憑證存放庫
App\Repository\Security\WebauthnCredentialRepository 實作:
findOneByCredentialId():查詢憑證findAllForUserEntity():取得使用者所有憑證saveCredentialSource():建立/更新憑證parseUserAgent():裝置名稱辨識