Nodge — Yii2 EAuth — регистрация, Identity, как делаете вы?

Использую расширение для Yii2, социальную авторизацию. от Nodge

У меня все настроено и все работает и так, но хочется сделать правильно, но ввиду малого опыта не могу пока придумать элегантное решение. Авторизация работает исправно, регистрацию писал свою.

Суть вопроса:
Собственно сам код автора я особо не менял, только расширил получение атрибутов от Api-шек. Сложность в том, что у меня выходят две Identity
Стандартна вида: __id: 3
Социальная вида: __id: vkontakte-484848

Есть код из коробки под Yii2 и на текущего авторизованного пользователя можно вытащить или показать профиль таким образом. аккаунты пользователя и профиля разделены в бд, но связаны один к одному. т.е. их Id Одинаковые. Я могу получить профиль так:
$modelProfile = Profile::find()->where(['id' => Yii::$app->user->identity->id])->one();


ввиду того, что модель USER и метод Identity Был расширен, можно по прешнему использовать метод который я указал выше. но проблема в то, что регистрация реализована так:
создается новый юзер. в поле service_id, service_name - запихиваются id юзера сервисное и имя сервиса.

и теперь что бы вытащить Id аккаунта нативное приходится делать что-то вроде такого куска кода в каждом контроллере, где есть взаимодействие.
protected function getSocialUser()
    {
        $identity = Yii::$app->getUser()->getIdentity();
        $user = User::find()->where(['service_id' => $identity->profile['id']])->one();
        $profile = Profile::find()->where(['id' => $user->id])->one();
        return $profile;
    }


И проводить проверки в местах получения:
$model = $this->getSocialUser();
        if(!isset($model)){
            $model = $this->findModel(Yii::$app->user->identity->id);
        }


причина того, что я не создаю юзеров с их же соц Id. ибо социальных сетей более 5. Потому боюсь как бы не было дубликатов. наданный момент оно работает и все исправно, но мне не нравится что это +2 запроса каждый раз, копипаста кода постоянная. И вынести код в отдельную модель не выйдет т.к. много где подобный подход используется. Какие решения могут быть и как можно переписать, вынести код? или изменить identity, иначе хранить в БД?
  • Вопрос задан
  • 1855 просмотров
Решения вопроса 1
sanchezzzhak
@sanchezzzhak
Ля ля ля...
я делал отдельную таблицу для соц авторизации

user - создовал тут запись
+
user_social - создовал тут запись, если пользовась авторизация через соц сеть
vendor str (vk fb ya mr tw итд)
user_id int
internal_id str

Таблица user_social использовалась только при входе или регистрации из соц.сетей
Если нужный данные из соц сетей, я создавал агитирующие поля в таблицах user или user_profile

UPD
public function actions()
    {
        return [
            'social' => [
                'class' => 'yii\authclient\AuthAction',
                'successCallback' => [$this, 'successCallback'],
            ],
        ];
    }

    /**
     * @param $client
     */
    public function successCallback($client)
    {
	$day = 86400;
        $client_id = Yii::$app->request->get('authclient');  // vk fb mr od etc
        $attributes = $client->getUserAttributes();             // result social data

        $userSocial = UserSocial::findOne(['client' => $client_id , 'internal_id' => $attributes['id'] ]);
        if(!$userSocial ){

            $user = new User;
            $user->scenario = 'social';

            if($user->register()){
                $userSocial = new UserSocial;
                $userSocial ->user_id = $user->id;
                $userSocial ->client  = $client_id;
                $userSocial ->internal_id = (string)$attributes['id'];
                $userSocial ->save();

                $prorile = $user->profile;
                $prorile->first_name = $attributes['first_name'];
                $prorile->last_name = $attributes['last_name'];
                $prorile->save();
            }
            Yii::$app->user->login($user, $day * 366 );
            Yii::$app->session->set('auth_social',[
                'client' => $client_id,
                'attributes' => $attributes,
                'token' => ''
            ]);

        }
        Yii::$app->user->login($user_social->user , $day * 366 );
    }

Вот так выводил список кнопок через что авторизоватся
<?php
        use yii\authclient\widgets\AuthChoice;
        $icons_id = [
            'vkontakte' => 1,
            'facebook' => 2,
            'tw' => 3,
            'mr' => 4,
            'odnoklassniki' => 5
        ];
        $authAuthChoice = AuthChoice::begin([
            'baseAuthUrl' => ['auth/social'],
        ]);?>
        <ul class="social-auth-list">
            <?php foreach ($authAuthChoice->getClients() as $client): ?>
                <li>
                    <a data-popup-width="500" data-popup-height="430"
                        href="<?= $authAuthChoice->createClientUrl($client)?>"><i class="ico ico-soc-<?=$icons_id[$client->getId()]?>"></i></a>
                </li>
            <?php endforeach; ?>
        </ul>
        <?php AuthChoice::end(); ?>

В конфиге
'authClientCollection' => [
            'class' => 'yii\authclient\Collection',
            'clients' => [
                'vkontakte' => [
                    'class' => 'yii\authclient\clients\VKontakte',
                    'clientId' => '1',
                    'clientSecret' => 'vW5AYsdsd',
                    'scope' => 'friends,email,offline',
                ],
                'facebook' => [
                    'class' => 'yii\authclient\clients\Facebook',
                    'clientId' => '1',
                    'clientSecret' => 'vW5AYsdsd',
                ],
                'odnoklassniki' => [
                    'class' => 'app\components\authclient\clients\Odnoklassniki',
                    'clientId' => '1',
                    'clientSecret' => 'F12sdsd',
                    'application_public_key' => 'vW5AYsdsdsdsd',
                    'scope' => 'VALUABLE_ACCESS'
                ],

            ],
        ],


Для ватосоцсети
<?php
namespace app\components\authclient\clients;
use yii\authclient\OAuth2;

/**
 * Class Odnoklassniki
 * @package app\components\authclient\clients
 * Example application configuration:
 *
 * ~~~
 * 'components' => [
 *     'authClientCollection' => [
 *         'class' => 'yii\authclient\Collection',
 *         'clients' => [
 *             'odnoklassniki' => [
 *                 'class' => 'yii\authclient\clients\odnoklassniki',
 *                 'clientId' => 'app_client_id',
 *                 'clientSecret' => 'application_client_secret',
 *                 'application_public_key' => 'application_public_key',
 *                 'scope' => 'VALUABLE_ACCESS'
 *             ],
 *         ],
 *     ]
 *     ...
 * ]
 */
class Odnoklassniki  extends OAuth2
{
    /**
     * @inheritdoc
     */
    public $authUrl = 'http://www.odnoklassniki.ru/oauth/authorize';
    /**
     * @inheritdoc
     */
    public $tokenUrl = 'http://api.odnoklassniki.ru/oauth/token.do';
    /**
     * @inheritdoc
     */
    public $apiBaseUrl = 'http://api.odnoklassniki.ru/fb.do';

    public $application_public_key;

    /**
     * @inheritdoc
     */
    protected function initUserAttributes()
    {
       return $this->api('','GET',[
           'method' => 'users.getCurrentUser',
           'format' => 'JSON',
           'application_key' => $this->application_public_key,
           'client_id' => $this->clientId,
       ]);
    }

    /**
     * @inheritdoc
     */
    protected function apiInternal($accessToken, $url, $method, array $params, array $headers)
    {
        $access_token = $accessToken->getToken();
        if (count($params)) {
            $param_str = '';
            ksort($params);
            foreach ($params as $k => $v)
            {
                $param_str .= $k . '=' . $v;
            }
            $params['sig'] = md5($param_str . md5($access_token . $this->clientSecret));
        }
        $params['access_token'] = $access_token;
        return $this->sendRequest($method, trim($url,'/'), $params, $headers);
    }

    /**
     * @inheritdoc
     */
    protected function defaultName()
    {
        return 'odnoklassniki';
    }

    /**
     * @inheritdoc
     */
    protected function defaultTitle()
    {
        return 'Odnoklassniki';
    }

    /**
     * @inheritdoc
     */
    protected function defaultNormalizeUserAttributeMap()
    {
        return [
            'id' => 'uid'
        ];
    }

}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы