Как сохранить access_token в БД, используя логин yii2-dektrium facebook? - PullRequest
0 голосов
/ 11 сентября 2018

Я использую yii2-dektrium, чтобы разрешить пользователям входить с учетными записями в Facebook.

После входа в систему мне нужно сделать запрос API с моего сервера, чтобы получить данные учетных записей пользователя.Один из примеров запроса:

$client = Yii::$app->authClientCollection->getClient('facebook');
$response = $client->createApiRequest()
        ->setMethod('GET')
        ->setUrl('v2.12/me/accounts')
        ->send();

access_token сохраняется в сеансе, поэтому мне необходимо сохранить его в базе данных.

Я уже добавил столбец access_token в social_account таблица по умолчанию yii2-dektrium, но я не знаю, как ее получить и сохранить, и, более того, как применить ее к запросам.

После прочтения некоторое время.Я думаю, что способ сохранить это переопределение метода connect в dektrium\user\controllers\SecurityController.

public function connect(ClientInterface $client)
{
    /** @var Account $account */
    $account = \Yii::createObject(Account::className());
    $event   = $this->getAuthEvent($account, $client);
    $this->trigger(self::EVENT_BEFORE_CONNECT, $event);
    $account->connectWithUser($client);
    $this->trigger(self::EVENT_AFTER_CONNECT, $event);
    $this->action->successUrl = Url::to(['/user/settings/networks']);
}

И для применения к запросу, переопределить applyAccessTokenToRequest на yii\authclient\clients\Facebook

public function applyAccessTokenToRequest($request, $accessToken)
{
    parent::applyAccessTokenToRequest($request, $accessToken);
    $data = $request->getData();
    if (($machineId = $accessToken->getParam('machine_id')) !== null) {
        $data['machine_id'] = $machineId;
    }
    $data['appsecret_proof'] = hash_hmac('sha256', $accessToken->getToken(), $this->clientSecret);
    $request->setData($data);
}

Я не могу это сделать.И я не уверен, что это правильный способ сделать это.Чего мне не хватает?

1 Ответ

0 голосов
/ 21 сентября 2018

Для сохранения access_token при первой необходимости перезаписать действие connect из \dektrium\user\controllers\SecurityController.

class SecurityController extends \dektrium\user\controllers\SecurityController
{
    public function connect(ClientInterface $client)
    {
        // default implementation of connect
        $account = \Yii::createObject(Account::className());
        $event   = $this->getAuthEvent($account, $client);
        $this->trigger(self::EVENT_BEFORE_CONNECT, $event);
        $account->connectWithUser($client);
        $this->trigger(self::EVENT_AFTER_CONNECT, $event);

        // get acess_token from $client
        $access_token['tokenParamKey'] = $client->getAccessToken()->tokenParamKey;
        $access_token['tokenSecretParamKey'] = $client->getAccessToken()->tokenSecretParamKey;
        $access_token['createTimestamp'] = $client->getAccessToken()->createTimestamp;
        $access_token['_expireDurationParamKey'] = $client->getAccessToken()->getExpireDurationParamKey();
        $access_token['_params'] = $client->getAccessToken()->getParams();

        // save acess_token to social_account table
        $model = SocialAccount::find()->where(['provider' => $client->getName()])->andWhere(['user_id' => Yii::$app->user->id])->one();
        $model->access_token = \yii\helpers\Json::encode($access_token);
        $model->save(false);

        $this->action->successUrl = Url::to(['/user/settings/networks']);
    }
}

Чтобы получить хранилище access_token в базе данных для дальнейших запросов API, создайте класс, который расширяет yii\authclient\SessionStateStorage и перезаписывает метод get.

namespace app\models\authclient;

class DbStateStorage extends SessionStateStorage
{
    public function get($key)
    {
        // $key is a complex string that ends with 'token' if the value to get is the actual access_token
        $part = explode('_', $key);
        if (count($part) == 3 && $part[2] == 'token') {
            $account = SocialAccount::find()
                ->where(['provider' => $part[1]])
                ->andWhere(['user_id' => Yii::$app->user->id])
                ->one();
            if ($account != null) {
                $access_token = json_decode($account->access_token);
                $token = new \yii\authclient\OAuthToken();
                $token->createTimestamp = $access_token->createTimestamp;
                $token->tokenParamKey = $access_token->tokenParamKey;
                $token->tokenSecretParamKey = $access_token->tokenSecretParamKey;
                $token->setParams((array)$access_token->_params);
                $token->setExpireDurationParamKey($access_token->_expireDurationParamKey);
                return $token;
            }
        }
        if ($this->session !== null) {
            return $this->session->get($key);
        }
        return null;
    }
}

Наконец установитеDbStateStorage на ваш authclient

class Facebook extends \dektrium\user\clients\Facebook
{
    public function __construct()
    {
        $this->setStateStorage('app\models\authclient\DbStateStorage');
    }
}
...