WordPress 自定义 JWT 授权和验证

WordPress 自带的 RESTful API 内置的身份验证方法是 Cookie Authentication ,登录仪表板时,会生成cookie。为了防止CSRF,需要在请求的地址后面,加上一个 nonce 参数“_wpnonce”。

CSRF请参考:https://javascript.net.cn/article?id=683

nonce生成,参考:https://verytheme.com/archives/136

如果想使用JWT(JSON Web Token),官方建议使用插件 https://wordpress.org/plugins/jwt-authentication-for-wp-rest-api/

但是这个插件只能使用用户名和密码登录,二次开发使用手机号或者验证码登录的话是不可以的,所以自己写了一个大概,可以完成注册、登录和验证。

一,WordPress JWT 用户注册接口

/* -------------------------------------------------------------------------- *
 * 用户注册接口 http://test.com/wp-json/verytheme/v1/register
 */
add_action('rest_api_init', 'register_route_hook');
function register_route_hook()
{
    register_rest_route('verytheme/v1', 'register', [
        'methods'  => 'POST',
        'callback' => 'register_callback'
    ]);
}


function register_callback($request)
{
    //获取注册页面提交时候的表单数据
    $redirect_to = sanitize_user($_REQUEST['redirect_to']) ? sanitize_user($_REQUEST['redirect_to']) : home_url();
    if (!empty($_POST['reg_flag'])) {
        $error = '';
        $sanitized_user_login       = sanitize_user($_POST['user_login']);
        $user_website               = sanitize_user($_POST['website']);
        $user_description           = sanitize_user($_POST['description']);
        $user_nickname              = sanitize_user($_POST['nickname']);
        $user_email                 = apply_filters('user_registration_email', $_POST['user_email']);


        // 验证邮箱
        if ($user_email == '') {
            // 一些代码 ...
        } 
        // 验证用户名
        if ($sanitized_user_login == '') {
            // 一些代码 ...
        }
        //验证密码
        if (strlen($_POST['user_pass']) < 6) {
            // 一些代码 ...
        }
        if ($error == '') {
            //验证全部通过进入注册信息添加
            $display_name = empty($user_nickname) ? $sanitized_user_login : $user_nickname;
            $user_pass = $_POST['user_pass'];
            $user_id = wp_insert_user(array(
                'user_login'    => $sanitized_user_login,
                'user_pass'     => $user_pass,
                'nickname'      => $user_nickname,
                'display_name'  => $display_name,
                'user_email'    => $user_email,
                'user_url'      => $user_website, 'description'   => $user_description
            ));
            //意外情况判断,添加失败
            if (!$user_id) {
                // 一些代码 ...
            }
        }
    }
}

二,WordPress JWT 登录接口

/* -------------------------------------------------------------------------- *
 * JWT 登录 http://test.com/wp-json/verytheme/v1/login
 */
add_action('rest_api_init', 'login_route_hook');
function login_route_hook()
{
    register_rest_route('verytheme/v1', 'login', [
        'methods'  => 'POST',
        'callback' => 'login_callback'
    ]);
}


function login_callback($request)
{
    $json = $request->get_json_params();
    $username = $json['username'];
    $password = $json['password'];


    global $wpdb;
    $user = $wpdb->get_results($wpdb->prepare("SELECT * FROM wp_users WHERE user_login=%s",$username));
    if(!$user){
        return new WP_Error(
            'jwt_auth_bad_request',
            '用户名或者密码错误',
            array(
                'status' => 403
            )
        );
    }


    if(!wp_check_password($password, $user[0]->user_pass)){
        return new WP_Error(
            'jwt_auth_bad_request',
            '用户名或者密码错误',
            array(
                'status' => 403
            )
        );
    }


    $res['token'] = createToken(1);
    $res['user']  = $user[0];


    return $res;
}



require_once get_template_directory() . "/extends/php-jwt/src/JWT.php";
require_once get_template_directory() . "/extends/php-jwt/src/BeforeValidException.php";
require_once get_template_directory() . "/extends/php-jwt/src/ExpiredException.php";
require_once get_template_directory() . "/extends/php-jwt/src/SignatureInvalidException.php";

三,WordPress JWT 生成JWT Token

/**
 * 生成JWT Token
 */
function createToken($user_id)
{
    $time                    = time();
    $payload['iat']          = $time;        // 签发时间
    $payload['exp']          = $time + 60*1000;   // 过期时间
    $payload['nbf']          = $time;        // 生效时间
    $payload['user_id']      = $user_id;  // 用户 ID
    $key    = defined('JWT_KEY') ? JWT_KEY : 'default_key';
    $token  = Firebase\JWT\JWT::encode($payload, $key);
    return $token;
}

四,验证JWT

默认情况下,筛选器使用此选项从请求的cookie(如果可用)中确定当前用户。所有的验证方法钩子都会调用determine_current_user过滤器,包括wp_validate_auth_cookie()。在生成JWT的时候,我们把user_id放入了JWT的Payload中,现在也可以在determine_current_user取出来,像中间价一样。

add_filter('determine_current_user', 'determine_current_user_callback' );
function determine_current_user_callback($user){

    $auth = isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : false;


    list($token) = sscanf($auth, 'Bearer %s');
    if (!$token) {
        // echo "fuck";
        return 0;
    }


    $key    = defined('JWT_KEY') ? JWT_KEY : 'default_key';


    try {
        $data = Firebase\JWT\JWT::decode($token, $key, array('HS256'));
    } catch(Exception $e) {
        // echo 'Message: ' .$e->getMessage();
        return 0;
    }


    return $data->user_id ? $data->user_id : 0;
}
收藏
评论
打赏
WordPress 主题开发
WordPress 常用的路径
2024-05-04
WordPress 主题开发
WP_Query 函数
2024-05-04
飞翔的鱼丸
39403 阅读
82 发布
2 收藏
动态
FishV 主题 v1.21.0 发布
LandV 企业主题 v2.8.0 发布
MirageV 主题 v2.6.4 发布
FishV 主题 v1.14 发布
MirageV 主题 v2.5 正式发布
BotV 插件 v1.7.0 发布
LandV 企业主题 v2.6.0 发布
MirageV 主题 v2.6.0 发布
生成中...
真诚赞赏,手留余香
登录
注册
重置密码