sweelix / yii2-oauth2-server

PHP 5.6+ 为 Yii 框架提供的 Oauth2 服务器集成

安装次数: 8,871

依赖项: 0

建议者: 0

安全: 0

星级: 61

关注者: 11

分支: 18

开放问题: 0

类型:yii2-extension

1.4.0 2018-11-05 21:33 UTC

This package is not auto-updated.

Last update: 2024-09-20 23:29:00 UTC


README

此扩展允许开发者使用 Oauth2 服务器。

Latest Stable Version Build Status Scrutinizer Code Quality Code Coverage License

Latest Development Version Build Status Scrutinizer Code Quality Code Coverage composer.lock

安装

如果您使用 Packagist 安装包,则可以更新您的 composer.json,如下所示

{
    "require": {
        "sweelix/yii2-oauth2-server": "~1.2.0"
    }
}

如何使用它

将扩展添加到您的配置中

return [
    //....
    'bootstrap' => [
        //....
        'oauth2',
        //....
    ],
    'modules' => [
        //....
        'oauth2' => [
            'class' => 'sweelix\oauth2\server\Module',
            'backend' => BACKEND,
            'db' => DB,
            'identityClass' => 'app\models\User', // only if you don't want to use the user identityClass
            //
            // Parameters
            //
        ],
        //....
    ],
    //....
];

您还需要启用 PrettyUrl

'components' => [
    //....
    'urlManager' => [
        'enablePrettyUrl' => true,
        'rules' => [
            // your rules go here
        ],
        // ....
    ]
    // ....
]

迁移(仅限 MySql)

所有需要的迁移都可以在 src/migrations 中找到。在应用它们之前,请确保已配置数据库连接。

授权类型

您可以在以下位置找到关于每种授权类型的示例和说明:这里这里

对于 Jwt Bearer 授权类型,您需要为指定的客户端和主题在数据库中创建一个 Jwt 条目。

配置模块

基本模块参数

  • backend:可以是 redismysql
  • db:组件或连接的 ID 或连接配置
  • identityClass:用于将 oauth2 授权系统链接到用户类的用户类,默认为用户组件的 identityClass
  • webUserParamId:允许在主应用程序用户(会话)和模块应用程序用户之间进行分离(默认为 __oauth2
  • identityCookieName:允许在主应用程序用户(Cookie)和模块应用程序用户之间进行分离(默认为 oauth2
  • webUser:允许完全管理模块 Web 用户(默认为 []
  • baseEndPoint:令牌和授权端点的基准路径,默认为 ''
  • overrideLayout:覆盖模块布局以使用另一个布局(例如:@app/views/layouts/oauth2)
  • overrideViewPath:覆盖视图路径以使用特定的视图路径(例如:@app/views/oauth2)

授权管理

  • allowImplicit:允许隐式授权(默认为 false
  • allowAuthorizationCode:允许授权代码授权(默认为 true
  • allowClientCredentials:允许客户端凭证授权(默认为 true
  • allowPassword:允许用户凭证/密码授权(默认为 true
  • allowCredentialsInRequestBody:允许在请求体中包含凭证(默认为 true
  • allowPublicClients:允许公共客户端(默认为 true
  • alwaysIssueNewRefreshToken:始终颁发新的刷新令牌(默认为 true
  • unsetRefreshTokenAfterUse:使用后删除刷新令牌(默认为 true

JWT 参数(:warning: 不确定实现。请自行承担风险!)

  • useJwtAccessToken:以 JWT 的形式发送访问令牌(默认:false
  • allowAlgorithm:JWT 可用的算法(默认:['RS256', 'RS384', 'RS512']
  • jwtAudience:默认为令牌端点
  • storeEncryptedTokenString:存储加密令牌(默认:true

生存时间

  • idTTL : ID令牌的TTL(默认为3600
  • accessTokenTTL : 访问令牌的TTL(默认为3600
  • refreshTokenTTL : 刷新令牌的TTL(默认为14 * 24 * 3600

基本Oauth名称

  • realm : Realm值(默认为Service
  • tokenQueryName : 访问令牌参数的名称(默认为access_token
  • tokenBearerName : 授权头的名称(默认为Bearer

强制参数

  • enforceState : 强制state参数(默认为true
  • allowOnlyRedirectUri : 需要确切的重定向URI(默认为true

OpenID

  • allowOpenIdConnect : 启用OpenId connect(默认:false)// 尚未实现

授权码参数

  • enforceRedirect : 强制重定向参数(默认为false
  • authorizationCodeTTL : 授权码的TTL(默认为30

CORS

  • cors : 在令牌端点上启用CORS(默认:false)CORS部分可以使用数组定义,如在Yii文档中所述
 return [
     //....
     'bootstrap' => [
         //....
         'oauth2',
         //....
     ],
     'modules' => [
         //....
         'oauth2' => [
             'class' => 'sweelix\oauth2\server\Module',
             'backend' => 'redis',
             'db' => 'redis',
             'identityClass' => 'app\models\User', // only if you don't want to use the user identityClass
             //
             // Cors parameters example :
             //
             'cors' => [
                'Origin' => ['https://www.myowndomain.com'],
             ]
         ],
         //....
     ],
     //....
 ];

用户身份和Web用户

配置用户组件以将oauth2系统和用户/身份管理链接起来

return [
    //....
    'components' => [
        //....
        'user' => [
            'class' => 'sweelix\oauth2\server\web\User',
            'identityClass' => 'app\models\User', // Identity class must implement UserModelInterface
            //
            // Parameters
            //
        ],
        //....
    ],
    //....
];

IdentityClass必须实现sweelix\oauth2\server\interfaces\UserModelInterface。您可以使用sweelix\oauth2\server\traits\IdentityTrait特质来自动实现

  • public function getRestrictedScopes()
  • public function setRestrictedScopes($scopes)
  • public static function findIdentityByAccessToken($token, $type = null)

您将需要实现其余的方法

  • public static function findByUsernameAndPassword($username, $password)
  • public static function findByUsername($username)

创建OAuth2的特定视图

为了使用自己的视图(而不是内置视图),您可以覆盖

  • layout : 模块参数overrideLayout
  • viewPath : 模块参数overrideViewPath

覆盖布局

您应该创建一个经典布局如

<?php
/**
 * @app/views/layouts/newLayout.php
 * @var string $content
 */
use yii\helpers\Html;

$this->beginPage(); ?>
    <!DOCTYPE html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title><?php echo Html::encode($this->title); ?></title>

        <meta name="viewport" content="width=device-width, initial-scale=1">

        <?php $this->head(); ?>
    </head>
    <body>
        <?php $this->beginBody(); ?>
            <?php echo $content;?>
        <?php $this->endBody(); ?>
    </body>

</html>
<?php $this->endPage();

并将其链接到模块

return [
    //....
    'modules' => [
        //....
        'oauth2' => [
            'class' => 'sweelix\oauth2\server\Module',
            'overrideLayout' => '@app/views/layouts/newLayout',
            //
            // Additional Parameters
            //
        ],
        //....
    ],
    //....
];

覆盖视图

您应该创建3个视图以允许oauth2模块按预期工作并将它们链接到模块

return [
    //....
    'modules' => [
        //....
        'oauth2' => [
            'class' => 'sweelix\oauth2\server\Module',
            // use views in folder oauth2
            'overrideViewPath' => '@app/views/oauth2',
            //
            // Additional Parameters
            //
        ],
        //....
    ],
    //....
];

错误视图

此视图用于在发生错误时显示页面

<?php
/**
 * error.php
 *
 * @var string $type error type
 * @var string $description error description
 */
use yii\helpers\Html;
?>

    <h1 class="alert-heading"><?php echo ($type ? : 'Unkown error'); ?></h1>
    <p><?php echo ($description ? : 'Please check your request'); ?></p>

登录视图

此视图用于在需要时显示登录页面

<?php
/**
 * login.php
 *
 * @var \sweelix\oauth2\server\forms\User $user
 *
 */
use yii\helpers\Html;
?>
    <?php echo Html::beginForm('', 'post', ['novalidate' => 'novalidate']); ?>
        <label>Username</label>
        <?php echo Html::activeTextInput($user, 'username', [
            'required' => 'required',
        ]); ?>
        <br/>
    
        <label>Password</label>
        <?php echo Html::activePasswordInput($user, 'password', [
            'required' => 'required',
        ]); ?>
        <br/>
        <button type="submit">LOGIN</button>
    <?php echo Html::endForm(); ?>

授权视图

此视图用于在需要时显示授权页面

<?php
/**
 * authorize.php
 *
 * @var \sweelix\oauth2\server\interfaces\ScopeModelInterface[] $requestedScopes
 * @var \sweelix\oauth2\server\interfaces\ClientModelInterface $client
 *
 */
use yii\helpers\Html;
?>
    <h1><?php echo $client->name ?> <span>requests access</span></h1>
    
    <?php echo Html::beginForm(); ?>
        <?php if(empty($requestedScopes) === false) : ?>
        <ul>
            <?php foreach($requestedScopes as $scope): ?>
            <li>
                <h4><?php echo $scope->id; ?></h4>
                <p>
                    <?php echo $scope->definition; ?>
                </p>
            </li>
            <?php endforeach; ?>
        </ul>
        <?php endif; ?>
            <!-- name of decline button **must be** decline -->
            <button type="submit" name="decline">DECLINE</button>
            <!-- name of accept button **must be** accept -->
            <button type="submit" name="accept">AUTHORIZE</button>
    <?php echo Html::endForm(); ?>

公开模型概述

OAuth2 Yii2扩展公开了多个模型,这些模型可用于您的应用程序。所有模型都可以使用Yii2 DI进行覆盖。

例如,如果您想覆盖Client模型,您必须使用以下方法在DI中注入自己的模型

Yii::$container->set('sweelix\oauth2\server\interfaces\ClientModelInterface', [
    'class' => YourClientModel::className(),
]);

Client / ClientModelInterface

  • Client::findOne($id) - 根据ID查找客户端
  • Client::findAllByUserId($id) - 根据用户ID查找所有接受的客户端
  • Client::findAll() - 查找所有现有客户端
  • $client->save() - 保存客户端
  • $client->delete() - 删除客户端
  • $client->hasUser($userId) - 检查用户(用户ID)是否接受了客户端
  • $client->addUser($userId) - 将用户(用户ID)附加到客户端
  • $client->removeUser($userId) - 从客户端中删除用户(用户ID)

AccessToken / AccessTokenModelInterface

  • AccessToken::findOne($id) - 根据ID查找accessToken
  • AccessToken::findAllByUserId($id) - 根据用户ID查找所有accessToken
  • AccessToken::findAllByClientId($id) - 根据客户端ID查找所有accessToken
  • AccessToken::deleteAllByUserId($id) - 删除所有用户(用户ID)的accessToken
  • AccessToken::deleteAllByClientId($id) - 删除所有客户端(客户端ID)的accessToken
  • AccessToken::findAll() - 查找所有现有的accessToken
  • AccessToken::deleteAllExpired() - 删除所有过期的accessToken
  • $accessToken->save() - 保存accessToken
  • $accessToken->delete() - 删除accessToken

RefreshToken / RefreshTokenModelInterface

  • RefreshToken::findOne($id) - 通过ID查找accessToken
  • RefreshToken::findAllByUserId($id) - 查找用户(userId)的所有刷新token
  • RefreshToken::findAllByClientId($id) - 查找客户端(clientId)的所有刷新token
  • RefreshToken::deleteAllByUserId($id) - 删除用户(userId)的所有刷新token
  • RefreshToken::deleteAllByClientId($id) - 删除客户端(clientId)的所有刷新token
  • RefreshToken::findAll() - 查找所有现有的刷新token
  • RefreshToken::deleteAllExpired() - 删除所有过期的刷新token
  • $refreshToken->save() - 保存刷新token
  • $refreshToken->delete() - 删除刷新token

AuthCode / AuthCodeModelInterface

  • AuthCode::findOne($id) - 通过ID查找authCode
  • $authCode->save() - 保存authCode
  • $authCode->delete() - 删除authCode

Scope / ScopeModelInterface

  • Scope::findOne($id) - 通过ID查找作用域
  • Scope::findAvailableScopeIds() - 查找所有作用域ID
  • Scope::findDefaultScopeIds() - 查找默认作用域ID
  • $scope->save() - 保存作用域
  • $scope->delete() - 删除作用域

CypherKey / CypherKeyModelInterface

  • CypherKey::findOne($id) - 通过ID查找密钥
  • $cypherKey->save() - 保存密钥
  • $cypherKey->delete() - 删除密钥
  • $cypherKey->generateKeys() - 为当前密钥生成随机密钥

Jti / JtiModelInterface (:警告:不确定实现。自行承担风险!)

  • Jti::findOne($id) - 通过ID查找jti
  • Jti::findAllBySubject($id) - 查找用户(userId)的所有jti
  • Jti::findAllByClientId($id) - 查找客户端(clientId)的所有jti
  • Jti::deleteAllBySubject($id) - 删除用户(userId)的所有jti
  • Jti::deleteAllByClientId($id) - 删除客户端(clientId)的所有jti
  • Jti::findAll() - 查找所有现有的jti
  • Jti::deleteAllExpired() - 删除所有过期的jti
  • Jti::getFingerprint($clientId, $subject, $audience, $expires, $jti) - 获取给定参数的jti指纹
  • $jti->save() - 保存jti
  • $jti->delete() - 删除jti

Jwt / JwtModelInterface (:警告:不确定实现。自行承担风险!)

  • Jwt::findOne($id) - 通过ID查找jwt
  • Jwt::getFingerprint($clientId, $subject) - 获取给定clientId和subject的jwt指纹
  • $jwt->save() - 保存jwt
  • $jwt->delete() - 删除jwt

将RBAC和作用域系统链接起来

使用sweelix\oauth2\server\web\User类将自动链接rbac系统和oauth2系统。

权限系统将稍作修改以允许细粒度检查

  • Yii::$app->user->can('read')将检查

    1. 当前客户端是否允许作用域read
    2. 当前用户是否允许rbac权限read
  • Yii::$app->user->can('rbac:read')将仅检查当前用户是否允许rbac权限read

  • Yii::$app->user->can('oauth2:read')将仅检查当前客户端是否允许作用域read

运行测试

在运行测试之前,您应该编辑文件tests/config/BACKEND.php并将配置更改为与您的环境匹配。

CLI系统

提供了一些命令来管理oauth2系统

  • php protected/yii.php oauth2:client/create
  • php protected/yii.php oauth2:client/update
  • php protected/yii.php oauth2:client/delete
  • php protected/yii.php oauth2:jwt/create
  • php protected/yii.php oauth2:jwt/update
  • php protected/yii.php oauth2:jwt/delete
  • php protected/yii.php oauth2:key/create
  • php protected/yii.php oauth2:key/update
  • php protected/yii.php oauth2:key/delete
  • php protected/yii.php oauth2:scope/create
  • php protected/yii.php oauth2:scope/update
  • php protected/yii.php oauth2:scope/delete
  • php protected/yii.php oauth2:cronjob/remove-expired - 使用cron管理器运行此命令
  • php protected/yii.php oauth2:migrate-redis/migrate - Redis迁移命令