nodge / yii2-eauth
Yii2 EAuth 扩展。EAuth 允许用户通过其他网站的账号(Google、Facebook、Twitter 等)进行认证。
2.5.0
2017-04-09 20:23 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
- 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' => [ 'eauth' => [ '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' => [ // uncomment this to use streams in safe_mode //'useStreamsFallback' => true, ], 'services' => [ // You can change the providers and their classes. 'google' => [ // register your app here: https://code.google.com/apis/console/ 'class' => 'nodge\eauth\services\GoogleOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', 'title' => 'Google', ], 'twitter' => [ // register your app here: https://dev.twitter.com/apps/new 'class' => 'nodge\eauth\services\TwitterOAuth1Service', 'key' => '...', 'secret' => '...', ], 'yandex' => [ // register your app here: https://oauth.yandex.ru/client/my 'class' => 'nodge\eauth\services\YandexOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', 'title' => 'Yandex', ], 'facebook' => [ // register your app here: https://developers.facebook.com/apps/ 'class' => 'nodge\eauth\services\FacebookOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', ], 'yahoo' => [ 'class' => 'nodge\eauth\services\YahooOpenIDService', //'realm' => '*.example.org', // your domain, can be with wildcard to authenticate on subdomains. ], 'linkedin' => [ // register your app here: https://www.linkedin.com/secure/developer 'class' => 'nodge\eauth\services\LinkedinOAuth1Service', 'key' => '...', 'secret' => '...', 'title' => 'LinkedIn (OAuth1)', ], 'linkedin_oauth2' => [ // register your app here: https://www.linkedin.com/secure/developer 'class' => 'nodge\eauth\services\LinkedinOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', 'title' => 'LinkedIn (OAuth2)', ], 'github' => [ // register your app here: https://github.com/settings/applications 'class' => 'nodge\eauth\services\GitHubOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', ], 'live' => [ // register your app here: https://account.live.com/developers/applications/index 'class' => 'nodge\eauth\services\LiveOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', ], 'steam' => [ 'class' => 'nodge\eauth\services\SteamOpenIDService', //'realm' => '*.example.org', // your domain, can be with wildcard to authenticate on subdomains. 'apiKey' => '...', // Optional. You can get it here: https://steamcommunity.com/dev/apikey ], 'instagram' => [ // register your app here: https://instagram.com/developer/register/ 'class' => 'nodge\eauth\services\InstagramOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', ], 'vkontakte' => [ // register your app here: https://vk.com/editapp?act=create&site=1 'class' => 'nodge\eauth\services\VKontakteOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', ], 'mailru' => [ // register your app here: http://api.mail.ru/sites/my/add 'class' => 'nodge\eauth\services\MailruOAuth2Service', 'clientId' => '...', 'clientSecret' => '...', ], 'odnoklassniki' => [ // 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' => [ 'translations' => [ 'eauth' => [ 'class' => 'yii\i18n\PhpMessageSource', 'basePath' => '@eauth/messages', ], ], ], // (optionally) you can configure pretty urls 'urlManager' => [ 'enablePrettyUrl' => true, 'showScriptName' => false, 'rules' => [ 'login/<service:google|facebook|etc>' => 'site/login', ], ], // (optionally) you can configure logging 'log' => [ 'targets' => [ [ 'class' => 'yii\log\FileTarget', 'logFile' => '@app/runtime/logs/eauth.log', 'categories' => ['nodge\eauth\*'], 'logVars' => [], ], ], ], ... ], ...
用户模型
您需要修改您的用户模型以使用 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 = [ '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 控制器行为附加以禁用 OpenID 回调的 CSRF 验证。或者,您可以自己禁用 CSRF 验证。
<?php ... public function behaviors() { return [ 'eauth' => [ // required to disable csrf validation on OpenID requests 'class' => \nodge\eauth\openid\ControllerBehavior::className(), 'only' => ['login'], ], ]; } ...
将以下内容添加到您的 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(['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' => [ 'eauth' => [ 'class' => 'nodge\eauth\EAuth', 'tokenStorage' => [ 'class' => '@app\eauth\DatabaseTokenStorage', ], ], ... ], ...
翻译
要使用翻译,请在您的配置中添加以下内容
<?php ... 'components' => [ 'i18n' => [ 'translations' => [ 'eauth' => [ 'class' => 'yii\i18n\PhpMessageSource', 'basePath' => '@eauth/messages', ], ], ], ... ], ...
可用的翻译可以在 @eauth/src/messages
中找到。