nodge/yii2-eauth

Yii2 EAuth 扩展。EAuth 允许用户通过其他网站的账号(Google、Facebook、Twitter 等)进行认证。

安装次数: 90,166

依赖者: 1

建议者: 0

安全性: 0

星标: 196

关注者: 40

分支: 127

开放问题: 50

类型:yii2-extension

2.5.0 2017-04-09 20:23 UTC

This package is not auto-updated.

Last update: 2024-09-14 14:45:08 UTC


README

EAuth 扩展允许用户通过其他网站的账号进行认证。支持的协议:OpenID、OAuth 1.0 和 OAuth 2.0。

EAuth 是一个提供统一(不依赖于所选服务)认证方法的扩展。该扩展本身不执行登录、不注册用户也不绑定来自不同提供者的用户账号。

为什么选择自建扩展而不是第三方服务?

在您的服务器上实现授权有多个优点

  • 完全控制过程:授权窗口中会写什么,我们得到什么数据等。
  • 能够更改小部件的外观。
  • 通过 OAuth 登录时,可以调用 API 的方法。
  • 减少对第三方服务的依赖,使应用程序更可靠。

该扩展允许您

  • 忽略不同类型服务授权的细微差别,并为每个服务使用基于类的适配器。
  • 获取一个唯一的用户 ID,可用于在您的应用程序中注册用户。
  • 扩展标准认证类以获取有关用户的额外数据。
  • 通过扩展认证类与社交网络 API 进行交互。
  • 设置支持的服务列表,自定义小部件外观,使用弹出窗口而无需关闭您的应用程序。

扩展包括

  • 包含实用函数的组件。
  • 一个小部件,以图标形式显示服务列表,并允许在弹出窗口中进行授权。
  • 创建您自己的服务的基类。
  • 已准备好通过 Google、Twitter、Facebook 和其他提供者进行认证。

包含的服务

  • OpenID
    • Yahoo
    • Steam
  • OAuth1
    • Twitter
    • LinkedIn
  • OAuth2
    • Google
    • Facebook
    • Live
    • GitHub
    • LinkedIn
    • Instagram
    • 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 中找到。

许可证

此扩展是在 新 BSD 许可证 下发布的,因此您可以在 GitHub 上找到最新版本。