Как переопределить Yii2 по умолчанию - ответ сервера Filsh Oauth

Я использую 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 (что не очень хорошо), чтобы удовлетворить мои требования. Что я сделал, я изменил эту строку в модели User:

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; 

}

Теперь все работает идеально, ПРОБЛЕМА, так как я изменил файл ядра bshaffer, когда я запускаю composer, он снова перезаписывает свой код по умолчанию, и мои изменения просто стираются каждый раз после запуска composer, мне снова нужно изменить один и тот же файл. Мне нужна правильная рабочая сила, может быть любой component где я переопределяю этот calss/method и помещаю свои изменения так, чтобы они были такими же после запуска composer.

1 ответ

Решение

Очевидно, что вы не должны ничего менять под vendor папку, потому что такие изменения будут отменены при следующем обновлении композитора.

Насколько я вижу, нет возможности настроить это, и что делает его более сложным, так это тот факт, что это проблема зависимой от расширения библиотеки, а не самого расширения. Сначала попытайтесь найти способ настроить это или добавить обходной путь без необходимости вносить такие изменения. Если вы не можете, возможные варианты:

1) Создайте запрос на выдачу / выдачу и дождитесь добавления изменений в bshaffer/oauth2-server-php, Удостовериться Filsh/yii2-oauth2-server имеет правильную зависимость, поэтому он позволяет обновить до более новой версии bshaffer/oauth2-server-php (еще один запрос на выпуск / извлечение для Filsh/yii2-oauth2-server вероятно, потребуется в этом случае). Это может занять довольно много времени.

2) Создайте вилки для обеих библиотек, внесите необходимые изменения и используйте их. Вы можете использовать раздел репозиториев в composer.json если вы не хотите публиковать его на Packagist. Смотрите больше информации в официальных документах Composer.

3) Скопируйте оба расширения в код своего проекта и поставьте под контроль версий, измените их и используйте вместо тех, которые в vendor папка.

4) Добавить обезьяну патч. Поскольку эта функция не поддерживается PHP изначально, вы можете использовать расширение, которое обеспечивает такую ​​функциональность - https://github.com/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 может занять много времени, и всегда есть вероятность, что ваш вопрос или запрос на отклонение будут отклонены. С вариантами 2 и 3 вы теряете возможность обновлений.

Если ты:

  • не может найти способ его настройки или обходного пути без необходимости вносить такие изменения;

  • нужно это срочно;

  • чувствую, что это похоже на особенность проекта, а не на общую.

используйте вариант 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.

Другие вопросы по тегам