zoukankan      html  css  js  c++  java
  • OAuth 2.0 Server PHP实现示例

    需求
    实现三方OAuth2.0授权登录

    使用OAuth服务
    OAuth 2.0 Server PHP

    环境
    nginx
    mysql
    php

    框架
    Yii

    一 安装

    项目目录下安装应用
    composer.phar require bshaffer/oauth2-server-php "^1.10"
    

    二 构建数据结构


    注意 user表需要自定义

    CREATE TABLE oauth_clients (
      client_id             VARCHAR(80)   NOT NULL,
      client_secret         VARCHAR(80),
      redirect_uri          VARCHAR(2000),
      grant_types           VARCHAR(80),
      scope                 VARCHAR(4000),
      user_id               VARCHAR(80),
      PRIMARY KEY (client_id)
    );
    
    CREATE TABLE oauth_access_tokens (
      access_token         VARCHAR(40)    NOT NULL,
      client_id            VARCHAR(80)    NOT NULL,
      user_id              VARCHAR(80),
      expires              TIMESTAMP      NOT NULL,
      scope                VARCHAR(4000),
      PRIMARY KEY (access_token)
    );
    
    CREATE TABLE oauth_authorization_codes (
      authorization_code  VARCHAR(40)     NOT NULL,
      client_id           VARCHAR(80)     NOT NULL,
      user_id             VARCHAR(80),
      redirect_uri        VARCHAR(2000),
      expires             TIMESTAMP       NOT NULL,
      scope               VARCHAR(4000),
      id_token            VARCHAR(1000),
      PRIMARY KEY (authorization_code)
    );
    
    CREATE TABLE oauth_refresh_tokens (
      refresh_token       VARCHAR(40)     NOT NULL,
      client_id           VARCHAR(80)     NOT NULL,
      user_id             VARCHAR(80),
      expires             TIMESTAMP       NOT NULL,
      scope               VARCHAR(4000),
      PRIMARY KEY (refresh_token)
    );
    
    CREATE TABLE oauth_users (
      username            VARCHAR(80),
      password            VARCHAR(80),
      first_name          VARCHAR(80),
      last_name           VARCHAR(80),
      email               VARCHAR(80),
      email_verified      BOOLEAN,
      scope               VARCHAR(4000),
      PRIMARY KEY (username)
    );
    
    CREATE TABLE oauth_scopes (
      scope               VARCHAR(80)     NOT NULL,
      is_default          BOOLEAN,
      PRIMARY KEY (scope)
    );
    
    CREATE TABLE oauth_jwt (
      client_id           VARCHAR(80)     NOT NULL,
      subject             VARCHAR(80),
      public_key          VARCHAR(2000)   NOT NULL
    );
    

    三 代码实现

    <?php
    /**
     * Created by PhpStorm.
     * User: parker
     * Date: 2020/9/8
     * Time: 7:08 下午
     *
     * 使用 OAuth 2.0 Server PHP 搭建三方授权服务
     * 相关文档地址 https://bshaffer.github.io/oauth2-server-php-docs/
     * 本服务使用 授权码形式
     * 授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。
     * 这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。
     *
     */
    
    namespace backendcontrollersapi;
    
    
    use commonlibLController;
    use commonlibLError;
    use commonmodelsadminAdminModel;
    use OAuth2GrantTypeAuthorizationCode;
    
    use OAuth2Request;
    use OAuth2Response;
    use OAuth2Server;
    use OAuth2StoragePdo;
    use yiihelpersJson;
    use Yii;
    
    class OauthController extends LController
    {
    
        public $enableCsrfValidation = false;
        /** @var Pdo $storage */
        public $storage;
        /** @var Server $server */
        public $server;
        /** @var Request $request */
        public $request;
        /** @var Response $response */
        public $response;
    
        public function init()
        {
    
            $this->storage  = new Pdo([
                'dsn' => 'mysql:host=10.0.80.10;dbname=ylsrc_admin',
                'username' => 'root',
                'password' => '2Q5@a5X6fh'
            ], [
                'client_table' => 'src_oauth_clients',
                'access_token_table' => 'src_oauth_access_tokens',
                'refresh_token_table' => 'src_oauth_refresh_tokens',
                'code_table' => 'src_oauth_authorization_codes',
                'user_table' => 'src_admin',
                'scope_table'  => 'src_oauth_scopes',
                'public_key_table'  => 'src_oauth_public_keys',
            ]);
            $this->server   = new Server($this->storage);
            $this->request  = Request::createFromGlobals();
            $this->response = new Response();
        }
    
    
        /**
         * 获取授权码(测试使用生产环境服务添加到登录接口)
         *
         * 获取链接
         * GET http://usrc.com/api/oauth/get-code?response_type=code&client_id=1&state=xyz
         * response_type    必填  请求类型
         * client_id        必填  三方授权id
         * state            必填  回调验证字段
         *
         * 响应方式为跳转到src_oauth_clients表对应id条目设置的redirect_url跳转连接返回第三方应用, 并且携带code
         * 示例:对应的redirect_url为 https://host.com 那么对应的跳转连接为(state未使用)
         * https://host.com?code=d53d363349951c29593b722a7d2fb05c054f5e65&state=xyz
         *
         */
        public function actionGetCode()
        {
            $uid = Yii::$app->user->id;
            if($uid){
                $this->server->addGrantType(new AuthorizationCode($this->storage)); // or any grant type you like!
                $this->server->validateAuthorizeRequest($this->request, $this->response);
                $this->server->handleAuthorizeRequest($this->request, $this->response, true, $uid);
                $this->response->send();
            }else{
                $this->ajaxReturn( LError::NO_PERMISSION, LError::getErrMsgByCode( LError::NO_PERMISSION ), [] );
            }
    
        }
    
        /**
         * 获取access_toke
         * 获取链接
         * POST     http://usrc.com/api/oauth/get-token
         * data
         * grant_type       必填  请求类型    authorization_code
         * client_id        必填  三方授权id
         * client_secret    必填  三方授权秘钥
         * code             必填  上一步获取的授权码
         *
         * return
         *
         * {
         * "access_token": "b2d91c2764bdde79e4f1e92349b969e8ee031e8a",
         * "expires_in": 3600,
         * "token_type": "Bearer",
         * "scope": null,
         * "refresh_token": "d9293e82c22523ad6500d6b584b484cc3aeb4736"
         * }
         */
        public function actionGetToken()
        {
            $response = $this->server->handleTokenRequest($this->request);
            $response->send();
        }
    
        /**
         * 使用token获取用户信息
         * 获取连接
         * GET  http://usrc.com/api/oauth/get-user-info?access_token=b2d91c2764bdde79e4f1e92349b969e8ee031e8a
         *
         * access_token 上一步获取的token
         *
         */
        public function actionGetUserInfo()
        {
            if (!$this->server->verifyResourceRequest($this->request)) {
                $this->server->getResponse()->send();
            }else{
                $token = $this->server->getAccessTokenData($this->request);
                $user  = AdminModel::findIdentity($token['user_id']);
                $data  = [
                    'id' => $user->id,
                    'username' => $user->account_name,
                    'mobile' => $user->mobile,
                    'email' => $user->email,
                ];
    
                echo Json::encode($data);
            }
    
        }
    }

     

    参考文献

    OAuth2.0 官方文档  https://oauth.net/2/

    OAuth 2.0 Server PHP 官方文档 https://bshaffer.github.io/oauth2-server-php-docs/

    OAuth2.0的一个简单解释 阮一峰 http://www.ruanyifeng.com/blog/2019/04/oauth_design.html

    OAuth2.0的四种方式 阮一峰 http://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html

     
  • 相关阅读:
    Linux Core Dump
    ODP.NET Managed正式推出
    获取EditText的光标位置
    (Java实现) 洛谷 P1603 斯诺登的密码
    (Java实现) 洛谷 P1603 斯诺登的密码
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1028 数的计算
  • 原文地址:https://www.cnblogs.com/haizizhu/p/13648429.html
Copyright © 2011-2022 走看看