结合使用WordPress REST API和JWT进行身份验证

背景

从 4.8.x 版本开始,WordPress 核心支持新 REST API。在众多新的可能性中,现在可以使用 React 或 Vue.js 之类的框架为网站、APP 或者小程序构建前端,并使用 WordPress 及其熟悉的管理仪表板来管理后端。

安装插件

使用 JWT Authentication for WP REST API 插件,因为它最早,简单稳定,与 WordPress Rest-API 无缝集成。

确保您的 Web 服务器支持 HTTP Authorization Header。如果使用共享主机,则默认情况下通常禁用此功能。要启用它,请将以下内容添加到您的 WordPress .htaccess 文件中:

RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]

安装完插件后,配置 secret key,向 wp-config.php 顶部添加:

// JWT Authentication
define('JWT_AUTH_SECRET_KEY', 'your-top-secret-key');

如果您需要获取随机 key,可以从 WordPress.org 的密钥服务中复制并粘贴。

JWT 使用 JWT_AUTH_SECRET_KEY 对 JSON Web 令牌进行签名。如果它被泄露,则您的站点的安全性将受到威胁!请勿泄露!

JWT_AUTH_CORS_ENABLE 激活COR,以增强安全性。

JWT 接口

JWT Authentication for WP REST API 插件使用 /jwt-auth/v1 命名空间添加了两个新的接口:

  • /wp-json/jwt-auth/v1/token (POST)
  • /wp-json/jwt-auth/v1/token/validate (POST)

第一个接口用来签发 token,接受包含用户名和密码的 POST 请求。

如果凭证已签出,则插件将发出 200 响应,其中包含带有 JSON 对象的令牌:token,user_display_name,user_email 和 user_nicename。

{
  "token": "eyJ0eXAiOiJKV1QiLC_A_RIDICULOUSLY_LONG_STRING_Ky4Y",
  "user_email": "example@baidu.com",
  "user_nicename": "example",
  "user_display_name": "Mr Example"
}

如果身份验证失败,则响应包括一个具有以下属性的对象:code,data 和 message。

然后将上面签发的 token 包含在对 WordPress REST API 的任何后续请求的 HTTP Authorization header 中。前端 APP 将需要将其存储在某个地方,例如 Cookie 或 localstorage 中。

第二接口用来验证 token。如果在 HTTP Auth 标头中发送了带有有效令牌的 POST 请求,它将返回以下响应:

{
  "code": "jwt_auth_valid_token",
  "data": {
    "status": 200
  }
}

正确的 Authorization 格式是:Bearer 空格 YOUR_TOKEN_HERE

鉴权登录

POST: /wp-json/jwt-auth/v1/token

{
  "username": "admin",
  "password": "password"
}

登录失败

{
  "code": "[jwt_auth] incorrect_password",
  "message": "提供的密码是无效的应用程序密码。",
  "data": {
    "status": 403
  }
}

登录成功

{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9qd3QuZGV2IiwiaWF0IjoxNDM4NTcxMDUwLCJuYmYiOjE0Mzg1NzEwNTAsImV4cCI6MTQzOTE3NTg1MCwiZGF0YSI6eyJ1c2VyIjp7ImlkIjoiMSJ9fX0.YNe6AyWW4B7ZwfFE5wJ0O6qQ8QFcYizimDmBy6hCH_8",
  "user_display_name": "admin",
  "user_email": "admin@localhost.dev",
  "user_nicename": "admin"
}

将 token 保存到本地存储,以后需要授权的接口就可以带上,插件会帮我们完成鉴权。

if (globals.currentUser && globals.currentUser.token) {
  config.headers.Authorization = 'Bearer ' + globals.currentUser.token;
}

登录失败

验证失败,返回值:

{
  "code": "jwt_auth_failed",
  "data": {
    "status": 403
  },
  "message": "Invalid Credentials."
}

校验 token 是否有效

有时候我们本地有 token,但是可能已失效,导致登录态异常,需要主动去验证。

POST: /wp-json/jwt-auth/v1/token/validate

只需要在 POST 的 header 里面加入一个 Authorization: Bearer 空格 TOKEN

验证通过后的返回值:

{
  "code": "jwt_auth_valid_token",
  "data": {
    "status": 200
  }
}

验证不通过后的返回值:

{
  "code": "jwt_auth_invalid_token",
  "message": "Signature verification failed",
  "data": {
    "status": 403
  }
}

自定义配置

永久有效的 token

插件默认的 token 有效期是 7 天,但是为了简化流程,我们一般将 token 设置为永久有效,当需要更新的时候,我们主动去更新它。

/**
 * 通过 jwt_auth_expire 这个filter,将token有效期设置为一年
 */
function fqht_jwt_auth_expire( $issuedAt ) {
  return $issuedAt + (DAY_IN_SECONDS * 365);
}
add_filter( 'jwt_auth_expire', 'fqht_jwt_auth_expire' );

故障排除

如果您发现无法发出经过身份验证的请求,例如尝试创建帖子,则可能是请求的 Authorization Header 未传递到 PHP 的问题。

一种解决方案是将以下指令添加到 WordPress .htaccess 文件的顶部。如果您不在共享主机环境中,则此指令的其他可能位置在 VirtualHost 配置或 apache 服务器 conf 中:

SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

如果您更新的是 conf 文件而不是.htaccess 文件,请不要忘记重启 apache 才能使设置生效!

未找到匹配 URL 和请求方式的路由。

{
  "code": "rest_no_route",
  "message": "未找到匹配URL和请求方式的路由。",
  "data": {
    "status": 404
  }
}

请确保已开启 JWT 插件。

Wrong number of segments

传递给 JWT 的参数错误,一般是 Authorization

参考

© 2022  Arvin Xiang
Built with ❤️ by myself