Skip to content
网游世界
网游世界

吾生有涯,而知无涯。

  • 首页
  • PHP
    • ThinkPHP
    • FastAdmin
    • webman
  • JavaScript
    • jQuery
    • AdminLTE
  • Free Pascal
  • Java
    • JeeSite
    • 若依
    • ruoyi-vue-pro
  • 其它
    • 操作系统
    • 树莓派
    • 前端
    • Null
  • 关于
网游世界

吾生有涯,而知无涯。

PHP OAuth2 Server 授权码授权

3Vshej, 2023年12月27日 周三

授权码

如果您曾经使用 Facebook 或 Google 帐户登录过 Web 应用程序,则授权码应该非常熟悉。

使用前提是,用户已经登录到了现有系统。

  • WEB 端,可以根据需要强制用户跳转
  • APP 端,可以返回特定标记,由 APP 端进行登录处理

第一部分

客户端查询参数发送到授权服务器:

  • response_type 响应类型,值为 code
  • client_id 客户端标识
  • redirect_uri 客户端重定向 URI。此参数是可选的,但如果不发送,用户将被重定向到预注册页面
  • scope 以空格分隔的范围列表
  • state 使用 CSRF 令牌。此参数是可选的,但强烈建议使用。您应该将 CSRF 令牌的值存储在用户的会话中,以便在用户返回时进行验证。

所有这些参数都将由授权服务器验证。

之后,将要求用户登录到授权服务器并授权客户端。

如果用户授权通过,则会将重定向到客户端指定的 URI 中,并包含以下参数:

  • code 授权码
  • state 原值返回,用于客户端数据处理、验证等。

第二部分

客户端将以下参数,发送到授权服务器:

  • grant_type 授权类型,值为 authorization_code
  • client_id 客户端标识
  • client_secret 客户端密钥
  • redirect_uri 使用相同的重定向 URI
  • code 使用查询字符串中的授权码

注意,您需要先解码 code 查询字符串。您可以使用 urldecode($code) 执行此操作。

授权服务器将以下 JSON 数据:

  • token_type 值为 Bearer
  • expires_in 令牌有效期( 整数)
  • access_token 访问令牌
  • refresh_token 用于过期前刷新访问令牌。

设置

无论在何处初始化对象,请初始化授权服务器的新实例并绑定存储接口和授权码:

// 初始化库
$clientRepository = new ClientRepository(); // ClientRepositoryInterface 实例
$scopeRepository = new ScopeRepository(); // ScopeRepositoryInterface 实例
$accessTokenRepository = new AccessTokenRepository(); // AccessTokenRepositoryInterface 实例
$authCodeRepository = new AuthCodeRepository(); // AuthCodeRepositoryInterface 实例
$refreshTokenRepository = new RefreshTokenRepository(); // RefreshTokenRepositoryInterface 实例
 
$privateKey = 'file://path/to/private.key';
//$privateKey = new CryptKey('file://path/to/private.key', 'passphrase'); // 如果私钥有密码
$encryptionKey = 'lxZFUEsBCJ2Yb14IF2ygAHI5N4+ZAUXXaSeeJm6+twsUmIen'; // 使用 base64_encode(random_bytes(32)) 生成
 
// 设置授权服务器
$server = new \League\OAuth2\Server\AuthorizationServer(
    $clientRepository,
    $accessTokenRepository,
    $scopeRepository,
    $privateKey,
    $encryptionKey
);
 
$grant = new \League\OAuth2\Server\Grant\AuthCodeGrant(
     $authCodeRepository,
     $refreshTokenRepository,
     new \DateInterval('PT10M') // 授权码 10 分钟后过期
 );
 
$grant->setRefreshTokenTTL(new \DateInterval('P1M')); // 刷新令牌 1 月后过期
 
// 在服务器上启用授权类型验证
$server->enableGrantType(
    $grant,
    new \DateInterval('PT1H') // 访问令牌在 1 小时后过期
);

实现

请注意:此处的这些示例演示了 Slim 框架的用法;Slim不是使用此库的必要条件,您只需要生成与 PSR7 兼容的 HTTP 请求和响应的东西。

客户端会将用户重定向到最终页面。

$app->get('/authorize', function (ServerRequestInterface $request, ResponseInterface $response) use ($server) {
 
    try {
 
        // 验证 HTTP 请求并返回 AuthorizationRequest 对象
        $authRequest = $server->validateAuthorizationRequest($request);
 
        // 认证请求对象可以被序列化并保存到用户的会话中
        // 此时,您可能希望将用户重定向到登录页
 
        // 用户登录后,在 AuthorizationRequest 上设置用户
        $authRequest->setUser(new UserEntity()); // UserEntityInterface 实例
 
        // 在这里,你应该将用户重定向到一个授权页面。
        // 这个表单会请求用户批准客户端和请求的作用域
 
        // 用户批准或拒绝,客户端就会更新状态
        // (true = 批准, false =拒绝)
        $authRequest->setAuthorizationApproved(true);
 
        // 返回 HTTP 重定向响应
        return $server->completeAuthorizationRequest($authRequest, $response);
 
    } catch (OAuthServerException $exception) {
 
        // 所有 OAuthServerException 实例都可以格式化成 HTTP 响应
        return $exception->generateHttpResponse($response);
 
    } catch (\Exception $exception) {
 
        // 未定义异常
        $body = new Stream(fopen('php://temp', 'r+'));
        $body->write($exception->getMessage());
        return $response->withStatus(500)->withBody($body);
 
    }
});

客户端将使用授权码请求访问令牌,以便创建 /access_token 端。

$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($server) {
 
    try {
 
        // 试着响应这个请求
        return $server->respondToAccessTokenRequest($request, $response);
 
    } catch (\League\OAuth2\Server\Exception\OAuthServerException $exception) {
 
        // 所有 OAuthServerException 实例都可以格式化成 HTTP 响应
        return $exception->generateHttpResponse($response);
 
    } catch (\Exception $exception) {
 
        // 未定义异常
        $body = new Stream(fopen('php://temp', 'r+'));
        $body->write($exception->getMessage());
        return $response->withStatus(500)->withBody($body);
    }
});

过期

token 过期后,需要通过接口返回的 refresh_token 值来,刷新 token。

相关文章:

  1. PHP OAuth2 Server league/oauth2-server 是用 PHP 编写的 OAuth 2.0 授权服务器的标准......
  2. PHP OAuth2 Server 隐性授权 隐性授权 不再推荐使用隐性授权。该授权方式仅出于遗留目的而记录在此处。行业最佳实践建议使用授权码,对......
  3. PHP OAuth Server 刷新令牌存储库接口文档 getNewRefreshToken() : RefreshTokenEntityInterface......
  4. PHP OAuth Server 范围存储库接口文档 getScopeEntityByIdentifier() : ScopeEntityInterfac......
PHP OAuthPHP授权验证

文章导航

Previous post
Next post

近期文章

  • Android Studio Gradle 配置国内镜像
  • 为什么重新发明轮子
  • ruoyi-vue-pro 匿名访问
  • VUE 中接收 code 异常
  • 关于 AI

归档

  • 2025 年 4 月
  • 2025 年 3 月
  • 2025 年 2 月
  • 2025 年 1 月
  • 2024 年 12 月
  • 2024 年 11 月
  • 2024 年 10 月
  • 2024 年 9 月
  • 2024 年 8 月
  • 2024 年 7 月
  • 2024 年 6 月
  • 2024 年 5 月
  • 2024 年 4 月
  • 2024 年 3 月
  • 2024 年 2 月
  • 2024 年 1 月
  • 2023 年 12 月
除非特殊说明,本站作品采用知识共享署名 4.0 国际许可协议进行许可。
豫公网安备 41010402002622号 豫ICP备2020029609号-3
©2025 3Vshej