实现默认 wordpress 登录表单登录后生成 jwt http only cookie

您希望在用户通过默认的 WordPress 登录表单登录后,生成一个包含 JWT(JSON Web Token)的 HTTP-only cookie。这是一种增强 WordPress 安全性的好方法,因为 HTTP-only cookie 不能被 JavaScript 访问,可以防止 XSS 攻击窃取认证信息。

要实现这个功能,您需要:

  1. 在用户成功登录后生成 JWT
  2. 将 JWT 设置为 HTTP-only cookie
  3. 在需要验证用户身份的地方验证这个 JWT

实现方案

WordPress 没有内置的 JWT 支持,所以您需要自己实现或使用插件。以下是一个自定义实现的方法:

1. 添加必要的 JWT 库

首先,您需要一个 PHP JWT 库。可以使用 Composer 安装 firebase/php-jwt

composer require firebase/php-jwt

2. 监听登录成功事件并生成 JWT

WordPress 有一个 wp_login 钩子,当用户成功登录时会触发。您可以使用这个钩子来生成 JWT 并设置为 cookie:

add_action('wp_login', 'set_jwt_auth_cookie', 10, 2);  
function set_jwt_auth_cookie($user_login, $user) {  
    // 引入 JWT 库  
    require_once __DIR__ . '/vendor/autoload.php';  
    use Firebase\JWT\JWT;  

    // 设置密钥(应该存储在安全的地方,比如 wp-config.php)  
    $secret_key = defined('JWT_AUTH_SECRET_KEY') ? JWT_AUTH_SECRET_KEY : 'your-secret-key';  

    // 设置 token 有效期(例如 12 小时)  
    $issued_at = time();  
    $expiration = $issued_at + (60 * 60 * 12);  

    // 准备 token 数据  
    $token_data = array(  
        'iss' => get_site_url(),  
        'iat' => $issued_at,  
        'exp' => $expiration,  
        'user' => array(  
            'id' => $user->ID,  
            'email' => $user->user_email,  
            'roles' => $user->roles  
        )  
    );  

    // 生成 JWT  
    $token = JWT::encode($token_data, $secret_key, 'HS256');  

    // 设置 HTTP-only cookie  
    setcookie(  
        'wp_jwt_token',  
        $token,  
        [  
            'expires' => $expiration,  
            'path' => '/',  
            'domain' => parse_url(get_site_url(), PHP_URL_HOST),  
            'secure' => is_ssl(),  
            'httponly' => true,  
            'samesite' => 'Strict'  
        ]  
    );  
}

3. 验证 JWT

您可以创建一个函数来验证 JWT:

function verify_jwt_token() {  
    // 如果用户已经通过 WordPress 标准方式登录,不需要验证 JWT  
    if (is_user_logged_in()) {  
        return true;  
    }  

    // 检查 JWT cookie 是否存在  
    if (!isset($_COOKIE['wp_jwt_token'])) {  
        return false;  
    }  

    require_once __DIR__ . '/vendor/autoload.php';  
    use Firebase\JWT\JWT;  
    use Firebase\JWT\Key;  

    $token = $_COOKIE['wp_jwt_token'];  
    $secret_key = defined('JWT_AUTH_SECRET_KEY') ? JWT_AUTH_SECRET_KEY : 'your-secret-key';  

    try {  
        // 解码并验证 token  
        $decoded = JWT::decode($token, new Key($secret_key, 'HS256'));  

        // 检查 token 是否过期  
        if ($decoded->exp < time()) {  
            return false;  
        }  

        // 如果需要,可以在这里设置当前用户  
        $user_id = $decoded->user->id;  
        wp_set_current_user($user_id);  

        return true;  
    } catch (Exception $e) {  
        return false;  
    }  
}

4. 与 REST API 集成

如果您需要在 REST API 中使用 JWT 认证,可以添加一个过滤器:

add_filter('rest_authentication_errors', 'jwt_authenticate_rest_api', 10, 1);  
function jwt_authenticate_rest_api($errors) {  
    // 如果已经通过其他方式认证,不干扰  
    if ($errors !== null) {  
        return $errors;  
    }  

    // 验证 JWT  
    if (verify_jwt_token()) {  
        return true;  
    }  

    // JWT 验证失败,返回错误  
    return new WP_Error(  
        'jwt_auth_failed',  
        __('JWT 认证失败'),  
        array('status' => 401)  
    );  
}

5. 在 wp-config.php 中设置密钥

为了安全起见,应该在 wp-config.php 中定义 JWT 密钥:

define('JWT_AUTH_SECRET_KEY', 'your-unique-secret-key-here');

建议使用 WordPress 的密钥生成 API 来生成一个强密钥:https://api.wordpress.org/secret-key/1.1/salt/

6. 处理登出

当用户登出时,您应该清除 JWT cookie:

add_action('wp_logout', 'clear_jwt_auth_cookie');  
function clear_jwt_auth_cookie() {  
    setcookie(  
        'wp_jwt_token',  
        '',  
        [  
            'expires' => time() - 3600,  
            'path' => '/',  
            'domain' => parse_url(get_site_url(), PHP_URL_HOST),  
            'secure' => is_ssl(),  
            'httponly' => true,  
            'samesite' => 'Strict'  
        ]  
    );  
}

完整实现示例

将以上代码整合到一个插件中:

<?php  
/**  
 * Plugin Name: WordPress JWT Authentication  
 * Description: 为 WordPress 添加 JWT 认证支持  
 * Version: 1.0  
 * Author: Your Name  
 */  

// 确保直接访问时退出  
if (!defined('ABSPATH')) {  
    exit;  
}  

// 引入 JWT 库  
require_once __DIR__ . '/vendor/autoload.php';  
use Firebase\JWT\JWT;  
use Firebase\JWT\Key;  

// 登录成功后设置 JWT cookie  
add_action('wp_login', 'set_jwt_auth_cookie', 10, 2);  
function set_jwt_auth_cookie($user_login, $user) {  
    // 设置密钥  
    $secret_key = defined('JWT_AUTH_SECRET_KEY') ? JWT_AUTH_SECRET_KEY : 'your-secret-key';  

    // 设置 token 有效期(例如 12 小时)  
    $issued_at = time();  
    $expiration = $issued_at + (60 * 60 * 12);  

    // 准备 token 数据  
    $token_data = array(  
        'iss' => get_site_url(),  
        'iat' => $issued_at,  
        'exp' => $expiration,  
        'user' => array(  
            'id' => $user->ID,  
            'email' => $user->user_email,  
            'roles' => $user->roles  
        )  
    );  

    // 生成 JWT  
    $token = JWT::encode($token_data, $secret_key, 'HS256');  

    // 设置 HTTP-only cookie  
    setcookie(  
        'wp_jwt_token',  
        $token,  
        [  
            'expires' => $expiration,  
            'path' => '/',  
            'domain' => parse_url(get_site_url(), PHP_URL_HOST),  
            'secure' => is_ssl(),  
            'httponly' => true,  
            'samesite' => 'Strict'  
        ]  
    );  
}  

// 验证 JWT  
function verify_jwt_token() {  
    // 如果用户已经通过 WordPress 标准方式登录,不需要验证 JWT  
    if (is_user_logged_in()) {  
        return true;  
    }  

    // 检查 JWT cookie 是否存在  
    if (!isset($_COOKIE['wp_jwt_token'])) {  
        return false;  
    }  

    $token = $_COOKIE['wp_jwt_token'];  
    $secret_key = defined('JWT_AUTH_SECRET_KEY') ? JWT_AUTH_SECRET_KEY : 'your-secret-key';  

    try {  
        // 解码并验证 token  
        $decoded = JWT::decode($token, new Key($secret_key, 'HS256'));  

        // 检查 token 是否过期  
        if ($decoded->exp < time()) {  
            return false;  
        }  

        // 设置当前用户  
        $user_id = $decoded->user->id;  
        wp_set_current_user($user_id);  

        return true;  
    } catch (Exception $e) {  
        return false;  
    }  
}  

// 与 REST API 集成  
add_filter('rest_authentication_errors', 'jwt_authenticate_rest_api', 10, 1);  
function jwt_authenticate_rest_api($errors) {  
    // 如果已经通过其他方式认证,不干扰  
    if ($errors !== null) {  
        return $errors;  
    }  

    // 验证 JWT  
    if (verify_jwt_token()) {  
        return true;  
    }  

    // JWT 验证失败,返回错误  
    return new WP_Error(  
        'jwt_auth_failed',  
        __('JWT 认证失败'),  
        array('status' => 401)  
    );  
}  

// 处理登出  
add_action('wp_logout', 'clear_jwt_auth_cookie');  
function clear_jwt_auth_cookie() {  
    setcookie(  
        'wp_jwt_token',  
        '',  
        [  
            'expires' => time() - 3600,  
            'path' => '/',  
            'domain' => parse_url(get_site_url(), PHP_URL_HOST),  
            'secure' => is_ssl(),  
            'httponly' => true,  
            'samesite' => 'Strict'  
        ]  
    );  
}

安全注意事项

  1. 确保使用强密钥并保持其安全
  2. 设置合理的 token 过期时间
  3. 使用 HTTPS 保护 cookie 传输
  4. 使用 HTTP-only 和 Secure 标志保护 cookie
  5. 考虑实现 token 刷新机制以延长会话

现有插件选项

如果您不想自己实现,可以考虑使用现有的插件:

  1. JWT Authentication for WP REST API
  2. Simple JWT Authentication
  3. WP REST API - JWT Authentication

这些插件提供了类似的功能,可能更容易集成到您的项目中。

Notes

在提供的代码片段中,我没有看到与 JWT 或 HTTP-only cookie 直接相关的代码。WordPress 核心没有内置 JWT 支持,所以需要自定义实现或使用第三方插件。上述解决方案基于 WordPress 的钩子系统和 PHP 的 cookie 功能,结合第三方 JWT 库来实现所需功能。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇