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

时间:2016-10-25 08:42:15

标签: php rest oauth yii2 oauth2-server

我使用的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 /方法并将我的更改放在运行作曲家之后它的ramians相同。

1 个答案:

答案 0 :(得分:3)

显然你不应该修改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 可能需要很长时间,您的问题或请求将始终被拒绝。选项 2 3 会导致更新失败。

如果你:

  • 无法进行配置或解决方法而无需进行此类更改;

  • 迫切需要这个;

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

使用选项 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();

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

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

选中related SO answer