一文接入 passKey

书接上回 php 接入单点 , 之前文章中说了接入 passKey
,但是看起来挺复杂,就先接入了单点登录,今天又查了些文章,学习了下,把 passKey
也啃了下来。
背景介绍
什么是 FIDO2?
FIDO2(Fast IDentity Online 2.0)是一个由 FIDO 联盟推出的开放认证标准,旨在通过公钥加密技术实现更安全、更便捷的无密码身份验证。FIDO2 标准由两个关键组件组成:
- WebAuthn:由 W3C 定义的 Web 认证标准,允许 Web 应用程序通过浏览器和平台级 API 进行安全的用户身份验证。
- CTAP(客户端到认证器协议):定义了浏览器或操作系统与认证设备(如安全密钥或生物识别传感器)之间的通信方式。
什么是 WebAuthn?
WebAuthn 是 FIDO2 标准的核心部分之一。它是一个由 W3C 标准化的 Web API,允许网站和应用程序通过浏览器注册和验证用户的公钥,并通过使用硬件认证器(如生物识别设备或安全密钥)进行身份验证。WebAuthn 消除了传统密码的使用,提高了安全性,并且使用户体验更加顺畅。
什么是 Passkey
Passkey 是 FIDO2 和 WebAuthn 技术的具体实现形式,它代表了一种无密码的用户身份验证方式。Passkey 本质上是基于 FIDO2 标准的公钥凭证,但它被设计得更加用户友好,通常与设备集成,比如手机或笔记本中的生物识别传感器。用户可以通过指纹、面部识别或设备 PIN 码来完成身份验证,无需记忆或输入复杂的密码。
三者的关系
- FIDO2 是整个无密码认证体系的框架和标准,规定了如何使用公钥加密进行身份验证。
- WebAuthn 是 FIDO2 框架中的 Web API,定义了浏览器与服务器之间的交互方式,支持多种认证方式。
- Passkey 是基于 FIDO2 和 WebAuthn 的具体应用形式,它让用户可以通过生物识别等方式轻松、安全地进行无密码登录。
总结来说,Passkey 是 FIDO2 和 WebAuthn 在实际应用中的一种具象化的表现,它利用了这些标准所提供的技术,旨在提供更安全、更便捷的身份验证体验。
mindmap root((FIDO2)) WebAuthn W3C标准 Web API 浏览器与服务器交互 CTAP 客户端到认证器协议 设备与认证器通信 Passkey 基于FIDO2标准 结合WebAuthn和CTAP 无密码身份验证 支持生物识别和设备集成
查阅资料
相关资料较少,先是看了一文搞懂 Passkey, 让我对 passkey 有了初步的认识,然后看了 Passkey 开发指南,感觉还是懂了点什么,但是还是有点模糊,于是我找到了 lbuchs/WebAuthn这款 PHP WebAuthn (FIDO2) 服务器库。通过阅读示例代码,开始着手进行开发。
开发过程一波 N 折,由于资料较少,认证流程理不清,最后看到了这篇文章 WebAuthn 在 php 中的实践,对我启发很大,现在终于明白了整体流程。
简单来说就是:
- 认证器注册
- 通过接口
a1
获取注册凭证,拿凭证调用浏览器navigator.credentials.create
- 拿认证结果调用
a2
,a2
校验并保存凭证信息,以供后续使用
- 通过接口
- 认证器登录
- 通过接口
b1
获取登录凭证,拿凭证调用浏览器navigator.credentials.get
- 拿结果调用
b2
,b2
校验凭证并进行登录
- 通过接口
开始开发
接入 WebAuthn,首先需要安装一个 PHP WebAuthn 库,我选择的是 lbuchs/WebAuthn。该库提供了简单易用的 API,支持 FIDO2 标准的无密码认证。
- 安装依赖
使用 Composer 安装 lbuchs/webauthn 库:
1 | composer require lbuchs/webauthn |
安装完成后,可以在项目中引用这个库,进行 WebAuthn 的开发。
- 配置 WebAuthn 服务器
在服务器端,我们需要配置 WebAuthn 服务来处理认证请求。以下是初始化 WebAuthn 对象的代码:
1 |
|
WebAuthn 构造函数的参数分别是:应用名称、RP ID(也就是你的域名)和 origin(通常是网站的 URL),由于我的登录仅仅我自己使用,就将用户写死在代码里了。
注册流程 (后台页面)
在用户注册阶段,我们需要让用户的浏览器生成一个新的认证器凭证,然后将其发送到服务器进行验证和保存。生成注册信息
首先,我们需要生成一个 challenge 并返回给客户端。challenge 是一个临时生成的随机字符串,用于防止重放攻击。
1
2
3
4
5
6
7
8
9
10
11
12
13function register($rpName, $rpId, $origin) {
global $user_name, $user_mail, $user_nick;
$webAuthn = getWebAuthnInstance($rpName, $rpId, $origin);
$createArgs = $webAuthn->getCreateArgs($user_name, $user_mail, $user_nick);
// 注意顺序,必须先获取参数,再请求getChallenge
$challenge = $webAuthn->getChallenge();
$_SESSION['webauthn_challenge'] = $challenge;
echo json_encode($createArgs);
}处理注册请求
用户在前端使用navigator.credentials.create
方法生成凭证后,浏览器会返回凭证信息。我们需要将这些信息发送到服务器进行验证和保存:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23function verifyRegistration($rpName, $rpId, $origin)
{
$webAuthn = getWebAuthnInstance($rpName, $rpId, $origin);
$data = json_decode(trim(file_get_contents('php://input')), null, 512, JSON_THROW_ON_ERROR);
$challenge = $_SESSION['webauthn_challenge'];
global $user_name, $user_mail, $user_nick;
try {
$clientDataJSON = !empty($data->clientDataJSON) ? base64_decode($data->clientDataJSON) : null;
$attestationObject = !empty($data->attestationObject) ? base64_decode($data->attestationObject) : null;
$data = $webAuthn->processCreate($clientDataJSON, $attestationObject, $challenge, true, true, false);
$data->userMail = $user_mail;
$data->userName = $user_name;
$data->userNick = $user_nick;
saveAuthenticator($data);
echo json_encode(['error' => 0, 'msg' => '注册成功']);
} catch (WebAuthnException $e) {
echo json_encode(['error' => 1, 'msg' => '注册失败: ' . $e->getMessage()]);
}
}
在这里,processCreate 方法用于验证浏览器传递过来的凭证数据,并返回认证器信息。接着我们可以将这些信息保存到数据库中,以便用户后续使用。
登录流程(登录页)
在用户登录时,我们需要从服务器获取一个登录挑战并发送到客户端,然后使用 navigator.credentials.get 方法进行认证。
- 生成登录挑战
和注册过程类似,我们需要先生成一个challenge
并返回给客户端:
1 | function authenticate($rpName, $rpId, $origin) |
- 处理登录请求
用户使用浏览器生成凭证后,将凭证信息发送到服务器进行验证:
1 | function verifyAuthentication($rpName, $rpId, $origin) |
在这里,processGet
方法用于验证用户的登录凭证。如果验证成功,我们就可以让用户登录系统。
完整代码
为了省事,全放一个文件里了 webauthn.php
1 |
|
前端代码
login.html,按钮 ID 为 login-webauthn
1 | if (!window.PublicKeyCredential) { |
后台
1 | function neWebauthn() { |
总结
通过 WebAuthn 和 FIDO2 的支持,我们可以轻松实现无密码的身份认证。本文介绍了从注册到登录的完整流程,并提供了相关的 PHP 代码示例。通过这些步骤,你可以在自己的项目中接入 Passkey,提高系统的安全性和用户体验。
完整代码参考 lbuchs/WebAuthn
官方仓库。如果你对 WebAuthn 或 FIDO2 标准有进一步的兴趣,可以查看 W3C 的 WebAuthn 标准文档。
- 标题: 一文接入 passKey
- 作者: tsvico
- 创建于 : 2024-08-18 21:59:23
- 更新于 : 2024-08-20 15:08:28
- 链接: https://blog.tbox.fun/2024/4152515392.html
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。