Wordpress 07 :: Wordpress启用OAuth

1,294 阅读3分钟

1. What & Why OAuth

1.1 什么是OAuth

准确的讲,其实我们这片文章介绍的是如何在Wordpress中使用OAuth2.0OAuth2.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-Serverinstall & activate

    image.png

3.2 修改Settings

  • Dashboard->OAuth Server->Settings

  • Enable OAuth Server

    image.png

3.3 新建Client

  • Dashboard->OAuth Server->Clients->Add New Client

  • 填写Client Name

  • 勾选Authorization Code,免费版本中只能选这个

    image.png

3.4 编写客户端

  • Dashboard->OAuth Server->Clients
  • 点击刚刚创建的Client
  • 记住ClientIDClientSecret,下面编写客户端时需要使用
  • 编写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: 前面创建的clientid

redirect_url: 登录成功后,要跳转回来的页面地址

  • 编写index.js
      1. 从跳转回来的页面中获取authorization-code,这个是30s过期
      1. 使用authorization-code, client_id, client_secret调用oauth/token获取access-token
      1. 使用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的问题。

image.png

上图中wordpress/data/htmlWordpress对应的文件夹,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时指定的页面。效果如下:

screen-capture.gif