起因

最近开始折腾无密码登录(Passkey)。

相比传统密码,Passkey 有几个明显优势:

  • 不需要记密码
  • 更安全(基于设备 + 生物识别)
  • 用户体验更好

于是我就想着:能不能把 WordPress 登录也升级成 Passkey?


什么是 Passkey?

简单说:

👉 Passkey = 基于 WebAuthn 的无密码登录方案

用户通过:

  • 指纹
  • 面容识别
  • 或设备 PIN

就可以完成登录,而不是输入密码。

背后原理是:

  • 公钥存在服务器
  • 私钥保存在用户设备

👉 所以不会被撞库 / 钓鱼攻击


先说我的结论(重点)

在 WordPress 实现 Passkey 有 3 种方案:

  1. 用插件(最简单)
  2. 调用 WebAuthn API 自己实现(推荐)
  3. 接入第三方认证(如 Firebase / Auth0)

    本文重点讲第 2 种:纯自定义实现


核心实现思路

实现 Passkey 登录,本质分两步:

1️⃣ 注册(绑定 Passkey)

流程:

  1. 用户登录后点击“绑定 Passkey”
  2. 前端调用:
navigator.credentials.create()
  1. 浏览器弹出生物识别
  2. 返回公钥
  3. 服务器保存公钥

2️⃣ 登录

流程:

  1. 用户点击“Passkey 登录”
  2. 前端调用:
navigator.credentials.get()
  1. 用户验证(指纹/FaceID)
  2. 返回签名
  3. 服务器验证签名
  4. 登录成功

🔧 WordPress 实现/调试(核心步骤)

✅ 第一步:创建接口(REST API)

在主题 functions.php 添加:

add_action('rest_api_init', function () {
    register_rest_route('passkey/v1', '/register', [
        'methods' => 'POST',
        'callback' => 'passkey_register',
    ]);

    register_rest_route('passkey/v1', '/login', [
        'methods' => 'POST',
        'callback' => 'passkey_login',
    ]);
});

✅ 第二步:保存公钥

function passkey_register($request) {
    $user_id = get_current_user_id();
    $publicKey = $request['publicKey'];

    update_user_meta($user_id, 'passkey_public_key', $publicKey);

    return ['status' => 'ok'];
}

✅ 第三步:验证登录

function passkey_login($request) {
    $username = $request['username'];
    $user = get_user_by('login', $username);

    if (!$user) {
        return ['error' => '用户不存在'];
    }

    $storedKey = get_user_meta($user->ID, 'passkey_public_key', true);

    // 这里应该做 WebAuthn 验证(建议用库)
    // 简化演示:

    wp_set_auth_cookie($user->ID);
    return ['status' => 'logged_in'];
}

🌐 前端实现(核心 JS)

注册 Passkey:

async function registerPasskey() {
    const cred = await navigator.credentials.create({
        publicKey: {
            challenge: new Uint8Array(32),
            rp: { name: "My Site" },
            user: {
                id: new Uint8Array(16),
                name: "user",
                displayName: "User"
            },
            pubKeyCredParams: [{ type: "public-key", alg: -7 }]
        }
    });

    console.log(cred);
}

登录:

async function loginPasskey() {
    const cred = await navigator.credentials.get({
        publicKey: {
            challenge: new Uint8Array(32)
        }
    });

    console.log(cred);
}

⚠️ 重要安全点(必须看)

上面只是“能跑”的示例,真实项目必须:

  • 使用 WebAuthn 库(PHP 推荐:web-auth/webauthn-lib)
  • challenge 必须由服务器生成
  • 验证签名必须在服务器完成
  • 不能只存 publicKey 字符串

👉 否则是不安全的


UI 接入(我的做法)

在登录页我做了三件事:

  • 保留原密码登录
  • 加一个 Passkey 登录按钮
  • 增加提示卡片

效果:

🔐 推荐使用 Passkey 登录
免密码 · 更安全 · 一键登录
[绑定管理]

👉 让用户逐步迁移,而不是强制切换


总结

这套方案的关键是:

  • 前端:WebAuthn API
  • 后端:验证签名
  • WordPress:只负责用户系统

🔚 后续优化方向

可以继续升级:

  • 自动检测浏览器是否支持 Passkey
  • 已绑定用户优先使用 Passkey
  • 隐藏密码登录入口
  • 多设备 Passkey 管理

💬 写在最后

Passkey 基本可以确定是未来趋势了。

这次算是把 WordPress 登录从:

👉 密码时代 → 无密码时代

如果你也在做网站,真的建议早点试试。