【问题标题】:How to override default Yii2 - Filsh Oauth Server response如何覆盖默认 Yii2 - Filsh Oauth Server 响应
【发布时间】:2016-10-25 21:40:46
【问题描述】:

我正在使用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 行

我改变了这个:

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

【问题讨论】:

  • 作为一个可能更好的选择,您是否考虑过实施 OpenID Connect?这将完成您在此处寻找的内容,而无需更改库。

标签: php rest oauth yii2 oauth2-server


【解决方案1】:

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

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

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 中的示例之外,我还发现article 也可以提供帮助,并提供类示例。在您的情况下,它更简单,并且会是这样的:

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错误)。

申请时使用类映射切换类bootstrap

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

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

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

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

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

检查此related SO answer

【讨论】:

  • 感谢您的宝贵回答,我有一个解决方法,我实施并交付了该项目,但现在因为我打算将来使用这个库,因此我想要一个适当的解决方法,您的第四个选项看起来不错但是我仍然不急于寻找更好的方法。
  • 很高兴为您提供帮助。请记住,如果您找到了不同的解决方案,您可以随时回答自己的问题并分享相关信息,这对其他人也很有用。
  • 解决方法与我修改了我在回答中提到的核心文件相同:) 这不是一个好方法,这就是为什么寻找一个合适的解决方案你的答案是有成效的,但仍在寻找更好的解决方案,可能任何其他人都可以提出更好的方法,否则您的第四个选项始终是开放的。 :)
  • 嗯,这种方法比金钱补丁要好得多,感谢您的宝贵时间和正确解决这个真正的 filsh oauth 库错误的方法。
  • @KamranKhatti 这不是错误。它是 Aouth2 应该如何工作的。我怀疑 PR 是否会被接受。当你有足够的它们时,这样的鳄鱼鸭解决方案最终会变得一团糟。我想说,尽可能遵循标准..
猜你喜欢
  • 2015-08-30
  • 2015-10-27
  • 1970-01-01
  • 2017-05-28
  • 2020-03-22
  • 2019-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多