4

我正在使用运行良好的Yii2 Filsh Oauth 服务器,但是当我登录时,它会生成带有默认字段的 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 行

我改变了这个:

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核心文件,它再次覆盖了它的默认代码,并且每次运行composer后我的更改都会被清除,我再次需要修改同一个文件。我需要一个适当的解决方法,可能是component我覆盖这个 calss/method 并放置我的更改,以便在运行 composer 后它运行相同。

4

1 回答 1

3

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

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

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

2)为两个库创建分支,进行所需的更改并使用它们。composer.json如果您不想在 Packagist 上发布它,可以使用 repositories 部分。在官方 Composer 文档中查看更多信息。

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

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

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

除了官方文档中的示例之外,我还找到了可以提供帮助的文章,并提供了类示例。在您的情况下,它更简单,并且会是这样的:

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()将类替换为您的自定义类。我对其进行了测试,它适用于扩展类。

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

在应用程序引导期间使用类映射切换类:

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

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

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

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

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

检查这个相关的 SO 答案

于 2016-10-25T12:23:20.260 回答