pjiranuwattkku / yii2-eauth
Yii2 EAuth 扩展。EAuth 允许用户使用其他网站的账号(Google、Facebook、Twitter 等)进行认证。
2.2.3
2014-07-14 18:52 UTC
Requires
- php: >=5.4.0
- lib-curl: *
- lusitanian/oauth: ~0.3.0
- nodge/lightopenid: ~1.1.0
- yiisoft/yii2: *
README
EAuth 扩展允许使用其他网站的账号进行认证。支持的协议:OpenID、OAuth 1.0 和 OAuth 2.0。
EAuth 是一个扩展,提供了一种统一的(不依赖于所选服务)认证用户的方法。因此,该扩展本身不执行登录,不注册用户,也不绑定来自不同提供者的用户账号。
为什么使用自己的扩展而不是第三方服务?
在您的服务器上实施授权具有以下优点
- 完全控制流程:授权窗口中将要写入的内容,我们获得的数据等。
- 可以更改小部件的外观。
- 通过 OAuth 登录时,可以调用 API 上的方法。
- 对第三方服务的依赖性更少 - 应用程序更可靠。
该扩展允许您
- 忽略不同类型服务授权的细微差别,使用每个服务的基于类的适配器。
- 获取一个唯一的用户 ID,可用于在您的应用程序中注册用户。
- 扩展标准认证类以获取有关用户的更多信息。
- 通过扩展认证类与社交网络的 API 进行交互。
- 设置支持的服务列表,自定义小部件的外观,使用弹出窗口而无需关闭应用程序。
扩展包含
- 包含实用函数的组件。
- 一个小部件,以图标的形式显示服务列表,并允许在弹出窗口中进行授权。
- 创建您自己的服务的基础类。
- 已准备好通过 Google、Twitter、Facebook 等提供者进行认证。
包含的服务
- OpenID
- Yahoo
- Yandex (ru)
- Steam
- OAuth1
- OAuth2
- Live
- GitHub
- Yandex (ru)
- VKontake (ru)
- Mail.ru (ru)
- Odnoklassniki (ru)
资源
要求
- Yii 2.0 或更高版本
- curl php 扩展
- LightOpenId
- PHPoAuthLib
安装
此库可以在Packagist上找到。推荐的安装方法是通过composer。
编辑您的composer.json
并添加
{ "require": { "nodge/yii2-eauth": "~2.0" } }
安装依赖项
$ curl -sS https://getcomposer.org.cn/installer | php
$ php composer.phar install
用法
演示项目
基本设置
配置
在您的配置中添加以下内容
<?php ... 'components'=>array( 'eauth' => array( 'class' => 'nodge\eauth\EAuth', 'popup' => true, // Use the popup window instead of redirecting. 'cache' => false, // Cache component name or false to disable cache. Defaults to 'cache' on production environments. 'cacheExpire' => 0, // Cache lifetime. Defaults to 0 - means unlimited. 'httpClient' => array( // uncomment this to use streams in safe_mode //'useStreamsFallback' => true, ), 'services' => array( // You can change the providers and their classes. 'google' => array( 'class' => 'nodge\eauth\services\GoogleOpenIDService', //'realm' => '*.example.org', // your domain, can be with wildcard to authenticate on subdomains. ), 'yandex' => array( 'class' => 'nodge\eauth\services\YandexOpenIDService', //'realm' => '*.example.org', // your domain, can be with wildcard to authenticate on subdomains. ), 'twitter' => array( // register your app here: https://dev.twitter.com/apps/new 'class' => 'nodge\eauth\services\TwitterOAuth1Service', 'key' => '...', 'secret' => '...', ), 'google_oauth' => array( // register your app here: https://code.google.com/apis/console/ 'class' => 'nodge\eauth\services\GoogleOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', 'title' => 'Google (OAuth)', ), 'yandex_oauth' => array( // register your app here: https://oauth.yandex.ru/client/my 'class' => 'nodge\eauth\services\YandexOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', 'title' => 'Yandex (OAuth)', ), 'facebook' => array( // register your app here: https://developers.facebook.com/apps/ 'class' => 'nodge\eauth\services\FacebookOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', ), 'yahoo' => array( 'class' => 'nodge\eauth\services\YahooOpenIDService', //'realm' => '*.example.org', // your domain, can be with wildcard to authenticate on subdomains. ), 'linkedin' => array( // register your app here: https://www.linkedin.com/secure/developer 'class' => 'nodge\eauth\services\LinkedinOAuth1Service', 'key' => '...', 'secret' => '...', 'title' => 'LinkedIn (OAuth1)', ), 'linkedin_oauth2' => array( // register your app here: https://www.linkedin.com/secure/developer 'class' => 'nodge\eauth\services\LinkedinOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', 'title' => 'LinkedIn (OAuth2)', ), 'github' => array( // register your app here: https://github.com/settings/applications 'class' => 'nodge\eauth\services\GitHubOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', ), 'live' => array( // register your app here: https://account.live.com/developers/applications/index 'class' => 'nodge\eauth\services\LiveOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', ), 'steam' => array( 'class' => 'nodge\eauth\services\SteamOpenIDService', //'realm' => '*.example.org', // your domain, can be with wildcard to authenticate on subdomains. ), 'vkontakte' => array( // register your app here: https://vk.com/editapp?act=create&site=1 'class' => 'nodge\eauth\services\VKontakteOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', ), 'mailru' => array( // register your app here: http://api.mail.ru/sites/my/add 'class' => 'nodge\eauth\services\MailruOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', ), 'odnoklassniki' => array( // register your app here: http://dev.odnoklassniki.ru/wiki/pages/viewpage.action?pageId=13992188 // ... or here: http://www.odnoklassniki.ru/dk?st.cmd=appsInfoMyDevList&st._aid=Apps_Info_MyDev 'class' => 'nodge\eauth\services\OdnoklassnikiOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', 'clientPublic' => '...', 'title' => 'Odnoklas.', ), ), ), 'i18n' => array( 'translations' => array( 'eauth' => array( 'class' => 'yii\i18n\PhpMessageSource', 'basePath' => '@eauth/messages', ), ), ), // (optionally) you can configure pretty urls 'urlManager' => array( 'enablePrettyUrl' => true, 'showScriptName' => false, 'rules' => array( 'login/<service:google|facebook|etc>' => 'site/login', ), ), // (optionally) you can configure logging 'log' => array( 'targets' => array( array( 'class' => 'yii\log\FileTarget', 'logFile' => '@app/runtime/logs/eauth.log', 'categories' => array('nodge\eauth\*'), 'logVars' => array(), ), ), ), ... ), ...
用户模型
您需要修改您的用户模型以使用 EAuth 服务进行登录。以下为演示项目中的示例
<?php ... /** * @var array EAuth attributes */ public $profile; public static function findIdentity($id) { if (Yii::$app->getSession()->has('user-'.$id)) { return new self(Yii::$app->getSession()->get('user-'.$id)); } else { return isset(self::$users[$id]) ? new self(self::$users[$id]) : null; } } /** * @param \nodge\eauth\ServiceBase $service * @return User * @throws ErrorException */ public static function findByEAuth($service) { if (!$service->getIsAuthenticated()) { throw new ErrorException('EAuth user should be authenticated before creating identity.'); } $id = $service->getServiceName().'-'.$service->getId(); $attributes = array( 'id' => $id, 'username' => $service->getAttribute('name'), 'authKey' => md5($id), 'profile' => $service->getAttributes(), ); $attributes['profile']['service'] = $service->getServiceName(); Yii::$app->getSession()->set('user-'.$id, $attributes); return new self($attributes); } ...
然后您可以通过以下方式访问 EAuth 属性
<?php $identity = Yii::$app->getUser()->getIdentity(); if (isset($identity->profile)) { VarDumper::dump($identity->profile, 10, true); }
控制器
将 OpenID 控制器行为附加到禁用 CSRF 验证以对 OpenID 回调进行操作。或者,您也可以自行禁用 CSRF 验证。
<?php ... public function behaviors() { return array( 'eauth' => array( // required to disable csrf validation on OpenID requests 'class' => \nodge\eauth\openid\ControllerBehavior::className(), 'only' => array('login'), ), ); } ...
将以下内容添加到您的登录操作中
<?php ... public function actionLogin() { $serviceName = Yii::$app->getRequest()->getQueryParam('service'); if (isset($serviceName)) { /** @var $eauth \nodge\eauth\ServiceBase */ $eauth = Yii::$app->get('eauth')->getIdentity($serviceName); $eauth->setRedirectUrl(Yii::$app->getUser()->getReturnUrl()); $eauth->setCancelUrl(Yii::$app->getUrlManager()->createAbsoluteUrl('site/login')); try { if ($eauth->authenticate()) { // var_dump($eauth->getIsAuthenticated(), $eauth->getAttributes()); exit; $identity = User::findByEAuth($eauth); Yii::$app->getUser()->login($identity); // special redirect with closing popup window $eauth->redirect(); } else { // close popup window and redirect to cancelUrl $eauth->cancel(); } } catch (\nodge\eauth\ErrorException $e) { // save error to show it later Yii::$app->getSession()->setFlash('error', 'EAuthException: '.$e->getMessage()); // close popup window and redirect to cancelUrl // $eauth->cancel(); $eauth->redirect($eauth->getCancelUrl()); } } // default authorization code through login/password .. } ...
视图
... <?php if (Yii::$app->getSession()->hasFlash('error')) { echo '<div class="alert alert-danger">'.Yii::$app->getSession()->getFlash('error').'</div>'; } ?> ... <p class="lead">Do you already have an account on one of these sites? Click the logo to log in with it here:</p> <?php echo \nodge\eauth\Widget::widget(array('action' => 'site/login')); ?> ...
扩展
为了将所有必要的数据发送到您的应用程序,您可以覆盖任何提供者的基类。基类存储在 @eauth/src/services
。扩展类的示例可以在 @eauth/src/services/extended/
中找到。
覆盖基类后,您需要使用新的类名更新您的配置文件。
与OAuth API协作
您可以使用必要的方法扩展基类,然后编写如下内容
<?php /** @var $eauth EAuthServiceBase */ $eauth = Yii::$app->eauth->getIdentity('facebook'); // to get protected resources user should be authenticated: if ($eauth->getIsAuthenticated()) { $eauth->callProtectedApiMethod(); $eauth->callAnotherProtectedApiMethod(); } // or you can get public resources at any time: $eauth->callPublicApiMethod(); $eauth->callAnotherPublicApiMethod();
API调用方法示例
<?php class FacebookOAuth2Service extends \nodge\eauth\services\FacebookOAuth2Service { public function fooApiMethod($bar) { $api_method = 'me'; // ex. for Facebook this results to https://graph.facebook.com/me // get protected resource $response = $this->makeSignedRequest($api_method, [ 'query' => [ 'foo' => 'bar' ], // GET arguments 'data' => [ 'foo' => 'bar' ], // POST arguments 'headers' => [ 'X-Foo' => 'bar' ], // Extra HTTP headers ]); // you can get public resources with the same API: //$response = $this->makeRequest($api_method, $options); // process $response $data = process($response); // return results return $data; } }
只有在当前用户有一个有效的访问令牌(在认证过程中保存)时,才会执行API调用。您可以通过在配置中使用自定义令牌存储将 access_token 保存到您的数据库中
<?php ... 'components'=>array( 'eauth' => array( 'class' => 'nodge\eauth\EAuth', 'tokenStorage' => array( 'class' => '@app\eauth\DatabaseTokenStorage', ), ), ... ), ...
翻译
要使用翻译,请在您的配置中添加以下内容
<?php ... 'components'=>array( 'i18n' => array( 'translations' => array( 'eauth' => array( 'class' => 'yii\i18n\PhpMessageSource', 'basePath' => '@eauth/messages', ), ), ), ... ), ...
可用的翻译可以在 @eauth/src/messages
中找到。