1. What
& Why
OAuth
1.1 什么是OAuth
?
准确的讲,其实我们这片文章介绍的是如何在Wordpress
中使用OAuth2.0
。OAuth2.0
是一种安全的协议,能够实现在不同系统中使用同一套用户系统,以实现在不同系统中对资源的保护。
具体的请大家参照阮一峰老师的这篇文章,介绍的非常好,本文就不花过多的篇幅来讨论概念了。
1.2 为什么要使用OAuth
?
如果我们是用Wordpress
作为门户网站,很多资源其实是存放在Wordpress
上的,在使用其他系统来对Wordpress
的资源进行访问和统计时,就需要有权限来访问Wordpress
上的资源,所以就需要使用OAuth
来解决这个问题。
2. Authorization Code
流程
OAuth2
提供了四种工作模式,最常见也是使用最广泛的就是Authorization Code
的方式。他的详细工作流程与工作原理,请参见阮一峰老师的这片文章。
本篇文章,我们只介绍简单的流程。
2.1 我们先做一些名词的解释,以方便大家理解:
Resource Owner
: 资源的所有者,本例中是Wordpress
,因为Wordpress
上保存所有我们要访问的资源。Authorization Server
: 授权服务器,也就是实现了OAuth2
的服务器,本例中还是Wordpress
,因为我们要在Wordpress
上启用OAuth2
。Client
: 要请求资源的系统,本例中,我们做了一个Demo
的网站,用来获取当前登录Wordpress
的用户,并获取用户的一些信息。
2.2 简单的Authorization Code
工作流程
- 用户访问
Client
系统 - 点击
Client
中的登录按钮,将链接到Authorization Server
提供的登录页面 - 在登录页面中登录,跳转
Authorization Server
将跳转回Client
系统 Client
调用Authroization Server
提供的api
获取access-token
Client
使用获取到access-token
调用Resource Owner
上的API
,来获取相应的资源
3. Wordpress
中启用OAuth
3.1 安装WP-OAuth-Server
-
Dashboard
->Plugins
->Add New
-
搜索
OAuth
-
选择
WP-OAuth-Server
,install
&activate
3.2 修改Settings
-
Dashboard
->OAuth Server
->Settings
-
Enable OAuth Server
3.3 新建Client
-
Dashboard
->OAuth Server
->Clients
->Add New Client
-
填写Client Name
-
勾选
Authorization Code
,免费版本中只能选这个
3.4 编写客户端
Dashboard
->OAuth Server
->Clients
- 点击刚刚创建的
Client
- 记住
ClientID
与ClientSecret
,下面编写客户端时需要使用 - 编写
index.html
<html>
<head>
<title>This is a test for WP-OAuth!!</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<h1>This is a test for WP-OAuth!!</h1>
<!--http://<authorization-server>/oauth/authorize?client_id=<client_id>&redirect_url=<client-site>&response_type=code-->
<a id="hyplinkLogin" href="https://yafeya-ncs.japaneast.cloudapp.azure.com/oauth/authorize?client_id=nU55y6BAEhaxwWn5A72BmiMcsLnPWCoyLyzjIFXa&redirect_uri=https://yafeya-ncs.japaneast.cloudapp.azure.com/wp-oauth-client-demo/&response_type=code">Login</a>
<button id="btnToken">Get Token</button>
<div id="user_infos" class="hide"></div>
</body>
<script src="axios.min.js"></script>
<script src="index.js"></script>
</html>
这个
login
对应的url
就是我们要跳转到的Authorization Server
对应的登录页面。格式是
http(s)://<authorization-server>/oauth/authorize?client_id=<client_id>&redirect_url=<client-site>&response_type=code
authorization-server
:wordpress
的地址
client_id
: 前面创建的client
的id
redirect_url
: 登录成功后,要跳转回来的页面地址
- 编写
index.js
-
- 从跳转回来的页面中获取
authorization-code
,这个是30s过期
- 从跳转回来的页面中获取
-
- 使用
authorization-code
,client_id
,client_secret
调用oauth/token
获取access-token
- 使用
-
- 使用
access-token
就可以调用resource-api
获取相应的资源
- 使用
-
(function (document) {
const client_id = "nU55y6BAEhaxwWn5A72BmiMcsLnPWCoyLyzjIFXa";
const client_sct = "d13rI1jGYcZHTJmUgAgSzxbXdNIrP1kYgtaKNmnL";
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
loginLink = document.querySelector("#hyplinkLogin");
tokenButton = document.querySelector("#btnToken");
tokenButton.addEventListener("click", async function (e) {
var request = {
"grant_type": "authorization_code",
"code": code,
"client_id": client_id,
"client_secret": client_sct,
"redirect_uri": "https://yafeya-ncs.japaneast.cloudapp.azure.com/wp-oauth-client-demo/"
};
var headers = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Authorization",
"Content-Type": "application/json"
};
try {
var response = await axios.post("https://yafeya-ncs.japaneast.cloudapp.azure.com/oauth/token", request, headers);
if (response.status == 200) {
var token = response.data.access_token;
console.log(`token: ${token}`);
var auth_token = `Bearer ${token}`;
var loginResponse = await axios.get("https://yafeya-ncs.japaneast.cloudapp.azure.com/oauth/me", {
headers: {
"Authorization": auth_token
}
});
if (loginResponse.status == 200) {
var user = loginResponse.data.user_login;
var email = loginResponse.data.user_email;
var roles = loginResponse.data.user_roles;
var infoArea = document.querySelector("#user_infos");
if(infoArea){
infoArea.classList.add("display");
var information = `
user: ${user}<br/>
email: ${email}<br/>
roles: ${roles.join()}<br/>
`;
infoArea.innerHTML = information;
}
}
}
} catch (error) {
console.log(error);
}
});
if (code) {
loginLink.classList.add("hide");
tokenButton.classList.add("display");
} else {
loginLink.classList.add("display");
tokenButton.classList.add("hide");
}
})(document);
3.5 部署
由于本Demo
也是使用了ajax
调用,所以也存在CORS
的问题,所以我把这个Demo
页面部署到了与Wordpress
相同的gateway
上面,用来解决CORS
的问题。
上图中wordpress/data/html
是Wordpress
对应的文件夹,wp-oauth-client-demo
是我们的demo
网页的文件夹。根据上图所示的文件结构,修改nginx.conf
如下
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name _;
root /var/www/html;
index index.php;
access_log /var/log/nginx/hakase-access.log;
error_log /var/log/nginx/hakase-error.log;
ssl_certificate /etc/ssl/fullchain.pem;
ssl_certificate_key /etc/ssl/private.pem;
ssl on;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass wordpress:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}
location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
expires max;
log_not_found off;
}
location /wp-oauth-client-demo {
index index.html;
}
}
最后的一个location /wp-oauth-client-demo
用来定义访问wp-oauth-client-demo
时指定的页面。效果如下: