sweelix / yii2-oauth2-server
PHP 5.6+ 为 Yii 框架提供的 Oauth2 服务器集成
Requires
- php: >=7.1.0
- ext-openssl: *
- bshaffer/oauth2-server-php: ~1.8
- yiisoft/yii2: ~2.0.13
- yiisoft/yii2-bootstrap: ~2.0
- yiisoft/yii2-redis: ~2.0
Requires (Dev)
- codeception/codeception: ~2.2
This package is not auto-updated.
Last update: 2024-09-20 23:29:00 UTC
README
此扩展允许开发者使用 Oauth2 服务器。
安装
如果您使用 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
:可以是 redis 或 mysqldb
:组件或连接的 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查找accessTokenAccessToken::findAllByUserId($id)
- 根据用户ID查找所有accessTokenAccessToken::findAllByClientId($id)
- 根据客户端ID查找所有accessTokenAccessToken::deleteAllByUserId($id)
- 删除所有用户(用户ID)的accessTokenAccessToken::deleteAllByClientId($id)
- 删除所有客户端(客户端ID)的accessTokenAccessToken::findAll()
- 查找所有现有的accessTokenAccessToken::deleteAllExpired()
- 删除所有过期的accessToken$accessToken->save()
- 保存accessToken$accessToken->delete()
- 删除accessToken
RefreshToken / RefreshTokenModelInterface
RefreshToken::findOne($id)
- 通过ID查找accessTokenRefreshToken::findAllByUserId($id)
- 查找用户(userId)的所有刷新tokenRefreshToken::findAllByClientId($id)
- 查找客户端(clientId)的所有刷新tokenRefreshToken::deleteAllByUserId($id)
- 删除用户(userId)的所有刷新tokenRefreshToken::deleteAllByClientId($id)
- 删除客户端(clientId)的所有刷新tokenRefreshToken::findAll()
- 查找所有现有的刷新tokenRefreshToken::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()
- 查找所有作用域IDScope::findDefaultScopeIds()
- 查找默认作用域ID$scope->save()
- 保存作用域$scope->delete()
- 删除作用域
CypherKey / CypherKeyModelInterface
CypherKey::findOne($id)
- 通过ID查找密钥$cypherKey->save()
- 保存密钥$cypherKey->delete()
- 删除密钥$cypherKey->generateKeys()
- 为当前密钥生成随机密钥
Jti / JtiModelInterface (:警告:不确定实现。自行承担风险!)
Jti::findOne($id)
- 通过ID查找jtiJti::findAllBySubject($id)
- 查找用户(userId)的所有jtiJti::findAllByClientId($id)
- 查找客户端(clientId)的所有jtiJti::deleteAllBySubject($id)
- 删除用户(userId)的所有jtiJti::deleteAllByClientId($id)
- 删除客户端(clientId)的所有jtiJti::findAll()
- 查找所有现有的jtiJti::deleteAllExpired()
- 删除所有过期的jtiJti::getFingerprint($clientId, $subject, $audience, $expires, $jti)
- 获取给定参数的jti指纹$jti->save()
- 保存jti$jti->delete()
- 删除jti
Jwt / JwtModelInterface (:警告:不确定实现。自行承担风险!)
Jwt::findOne($id)
- 通过ID查找jwtJwt::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')
将检查- 当前客户端是否允许作用域
read
- 当前用户是否允许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迁移命令