如何覆盖默认的 Yii2 - Filsh Oauth 服务器响应

How to override default Yii2 - Filsh Oauth Server response

我正在使用 Yii2 Filsh Oauth Server,它工作正常,但是当我登录时,它会生成带有默认字段的 AccessToken,即

{
  "access_token": "f3389e81c234276967079b2293795fc9104a2fac",
  "expires_in": 86400,
  "token_type": "Bearer",
  "user_id": 9,
  "scope": null,
  "refresh_token": "851464a210f56bb831da378a43e1016bd3e765d7",
}

但我需要在其响应中添加用户信息,例如

{
  "access_token": "f3389e81c234276967079b2293795fc9104a2fac",
  "expires_in": 86400,
  "token_type": "Bearer",
  "scope": null,
  "refresh_token": "851464a210f56bb831da378a43e1016bd3e765d7",
  "user": {
    "id": 9,
    "first_name": "Test",
    "last_name": "Test2",
    "username": "test",
    "email": "test@gmail.com",
    "status": 1,
    "dob": "20-08-1990",
    "gender": "Male",
   }
}

我想出了一个奇怪的解决方法我定制了 bshaffer 核心库文件(这不是一个好方法)来满足我的要求,我做了什么,我在用户模型中更改了这一行:

return ['user_id' => $user->getId()];

至此

return ['user_id' => [$user->getId(), $userObject]]; //I get all user info in $userObject and passed an array with two fields

因为我传递的是数组而不是单个数组 $user->getId() 因此我需要修改 bshaffer 库文件 AccessToken.php ,该文件可在以下路径获得:vendor/bshaffer/oauth2-server-php/src/OAuth2/ResponseType/AccessToken.php 第 76 行 [=20] =]

我更改了这个:

public function createAccessToken($client_id, $user_id, $scope = null, $includeRefreshToken = true)
{
  $token = array(
        "access_token" => $this->generateAccessToken(),
        "expires_in" => $this->config['access_lifetime'],
        "token_type" => $this->config['token_type'],
        "user_id" => $user_id,
        "scope" => $scope
    );

  $this->tokenStorage->setAccessToken($token["access_token"], $client_id, $user_id, $this->config['access_lifetime'] ? time() + $this->config['access_lifetime'] : null, $scope);

  if ($includeRefreshToken && $this->refreshStorage) {
        $token["refresh_token"] = $this->generateRefreshToken();
        $expires = 0;
        if ($this->config['refresh_token_lifetime'] > 0) {
            $expires = time() + $this->config['refresh_token_lifetime'];
        }
        $this->refreshStorage->setRefreshToken($token['refresh_token'], $client_id, $user_id, $expires, $scope);
    }
  return $token;
}

对此:

public function createAccessToken($client_id, $user_id, $scope = null, $includeRefreshToken = true)
{
  $token = array(
        "access_token" => $this->generateAccessToken(),
        "expires_in" => $this->config['access_lifetime'],
        "token_type" => $this->config['token_type'],
        "scope" => $scope,
        "user" => $user_id[1] //NOTE: I added new user field and passed second index of array which is user node
    );

//NOTE: Here I passed $user_id[0] since $user_id is array hence I am using its 0 index here which has id
$this->tokenStorage->setAccessToken($token["access_token"], $client_id, $user_id[0], $this->config['access_lifetime'] ? time() + $this->config['access_lifetime'] : null, $scope);

  if ($includeRefreshToken && $this->refreshStorage) {
        $token["refresh_token"] = $this->generateRefreshToken();
        $expires = 0;
        if ($this->config['refresh_token_lifetime'] > 0) {
            $expires = time() + $this->config['refresh_token_lifetime'];
        }
        //NOTE: Same goes here passing $user_id[0]
        $this->refreshStorage->setRefreshToken($token['refresh_token'], $client_id, $user_id[0], $expires, $scope);
    }

  return $token; 

}

现在一切正常 问题 是因为我在 运行 composer 时修改了 bshaffer 核心文件,它再次覆盖了它默认代码和我的更改每次都在 运行ning composer 之后被清除,我再次需要修改同一个文件。我需要一个适当的解决方法可能是任何 component,我覆盖这个 calss/method 并放置我的更改,以便它在 运行ning composer 之后保持相同。

显然,您不应修改 vendor 文件夹下的任何内容,因为此类更改将在下一次 composer 更新时被覆盖。

据我所知,没有配置它的选项,而使它变得更难的是,这是扩展依赖库的问题,而不是扩展本身的问题。首先尝试找到一种方法来配置它或添加解决方法而无需进行此类更改。如果你不能,可能的选择是:

1) 创建问题/拉取请求并等待 bshaffer/oauth2-server-php 中添加更改。确保 Filsh/yii2-oauth2-server 具有正确的依赖关系,以便它允许更新到 bshaffer/oauth2-server-php 的较新版本(在这种情况下可能需要 Filsh/yii2-oauth2-server 的另一个问题/拉取请求)。这可能需要很长时间。

2) 为两个库创建分支,进行所需的更改并改用它们。如果你不想在 Packagist 上发布它,你可以使用 composer.json 中的存储库部分。在 official Composer docs.

中查看更多信息

3) 将两个扩展复制到您的项目代码中并置于版本控制之下,修改它们并使用而不是 vendor 文件夹中的扩展。

4) 添加猴子补丁。由于 PHP 本身不支持此功能,您可以使用提供此类功能的扩展 - antecedent/patchwork.

在这种情况下,您可以将此方法替换为您自己的方法。

除了 official docs, I found article 中的示例也有帮助,还有 classes 中的示例。在你的情况下,它更简单,就像这样:

replace(\OAuth2\ResponseType:AccessToken:class. '::createAccessToken', function ($client_id, $user_id, $scope = null, $includeRefreshToken = true) {
    // Redefine method behavior as you want here
});

选项 1 可能需要很长时间,并且您的问题或拉取请求总是有可能被拒绝。使用选项 23 您将失去更新的可能性。

如果你:

  • 找不到无需进行此类更改的配置方法或解决方法;

  • 急需这个;

  • 感觉它看起来像项目特定功能而不是通用功能。

使用选项 4,这可能是这种情况下的最佳选择。

更新:

这是另一个使用 Yii2 内置功能的选项。

5) 您可以使用 Yii::$classMap() 将 class 替换为自定义的。我对其进行了测试,它与扩展 classes.

配合使用效果很好

复制 vendor/bshaffer/oauth2-server-php/src/OAuth2/ResponseType/AccessToken.php 并粘贴到 common/components 文件夹中。修改createAccessToken方法,但不要修改命名空间(否则会出现Class not found错误)。

在应用程序期间使用 class 地图切换 class bootstrap:

Yii::$classMap['OAuth2\ResponseType\AccessToken'] = '@common/components/AccessToken.php';

您可以在应用程序初始化之前将它放在 index.php 并且 运行:

$application = new yii\web\Application($config);
$application->run();

但是我建议创建单独的 bootstrap 组件实现 BootstrapInterface 并将其包含在应用程序配置中。

现在,当引用 OAuth2\ResponseType\AccessToken 时,您的自定义 class 将被使用。缺点是您不能从扩展 class 扩展并只覆盖一种方法,但那是因为您需要保留原始命名空间。

检查此