この問題には2つの解決策があります。
- Loginzaなどの承認サービスを使用します。
- サービスごとに独立して認証機能を実装します。
認証サービスを使用する長所:
- インストールのシンプルさと速度。
- 各プロバイダーを通じて承認の複雑さを学ぶ必要はありません。
ただし、自己認証には他にもいくつかの利点があります。
- 認証プロセスの完全な制御:プロバイダー認証ウィンドウに書き込まれる内容、受信するデータなど。
- サイトの設計に応じて承認ウィジェットの外観を変更する機能。
- OAuthを介して認証する場合、プロバイダーから提供されている場合、APIメソッドを呼び出すことができます。
- サードパーティのサービスへの依存度が低くなり、信頼性が高まります。
私は主にyiiの既製の拡張機能がないため、2番目のオプションを選択しました。そのような認証システムが内部からどのように機能するのか疑問に思いました。 最初は、ユーザー管理モジュールの一部でした。 しかし、後にこの機能は別の拡張機能として割り当てられ、どのプロジェクトでも簡単に使用できます。
1.認証システムの要件
拡張機能を設計するとき、私は次の原則に導かれました。
- さまざまなタイプのサービスを介した複雑な認可、各サービスでのアダプターの使用を無視する必要性。
- アプリケーションにユーザーを登録するために使用できる一意の認証識別子を取得します。
- 標準の許可クラスを拡張して、追加のユーザー情報を取得する機能。
- 必要なサービスの許可クラスを拡張することにより、ソーシャルネットワークのAPIを操作する機能。
- サイトでサポートされるサービスのリストをカスタマイズする機能により、承認ウィジェットの外観を再定義します。 アプリケーションを閉じずに、承認のためにポップアップウィンドウを使用する機能。
2. EAuth拡張
上記のすべての要件を実装した結果、EAuth拡張機能が生まれました。
現時点では、拡張機能には次のものが含まれています。
- ヘルパー関数を含むコンポーネント。
- アイコンの形式でサービスのリストを表示し、ポップアップウィンドウで認証を許可するウィジェット。
- OpenIDまたはOAuthに基づくサービスを追加するための基本クラス。
- Google、Yandex、Twitter、Facebook、VKontakte、およびMail.ruによる承認のための既製のクラス。
3.インストール
最初に、
`protected/extensions/eauth`
機能をダウンロードして解凍する必要があります 。
3.1依存関係
拡張機能は、ロイドとEOAuthを使用して、それぞれOpenIDとOAuthを操作します。 これらの拡張機能をダウンロードして、
`protected/extensions`
ディレクトリに配置する必要があります。
3.2セットアップ
`main.php`
の設定では
`main.php`
を追加する必要があります:
'import'=>array( 'ext.eoauth.*', 'ext.eoauth.lib.*', 'ext.lightopenid.*', 'ext.eauth.services.*', ), 'components'=>array( 'loid' => array( 'class' => 'ext.lightopenid.loid', ), 'eauth' => array( 'class' => 'ext.eauth.EAuth', 'popup' => true, // Use the popup window instead of redirecting. 'services' => array( // You can change the providers and their classes. 'google' => array( 'class' => 'GoogleOpenIDService', ), 'yandex' => array( 'class' => 'YandexOpenIDService', ), 'twitter' => array( 'class' => 'TwitterOAuthService', 'key' => '...', 'secret' => '...', ), 'facebook' => array( 'class' => 'FacebookOAuthService', 'client_id' => '...', 'client_secret' => '...', ), 'vkontakte' => array( 'class' => 'VKontakteOAuthService', 'client_id' => '...', 'client_secret' => '...', ), 'mailru' => array( 'class' => 'MailruOAuthService', 'client_id' => '...', 'client_secret' => '...', ), ), ), ),
拡張機能には、
popup
と
services
2つのパラメーターしかありません。
popup
パラメーターは、プロバイダーのサイトにリダイレクトする代わりに、承認のためにポップアップウィンドウを使用する役割を果たします。
services
パラメーターは、アプリケーションでサポートされているプロバイダーのリストです。 プロバイダーごとに、プロバイダーの基本クラスに基づいて独自のクラスを指定できます。 OAuthプロバイダーのキーを取得するには、適切なプロバイダーにアプリケーションを登録する必要があります。
4.使用する
例として、
`yiic webapp create`
によって生成された標準のYiiアプリケーションを取り上げ、GoogleおよびYandexを介して認証オプションを追加します(キーを混乱させないようにOAuthプロバイダーを接続しません)。 完成したデモをご覧ください 。
4.1 UserIdentity
最初に、拡張機能を使用してログインする
ServiceUserIdentity
クラスを作成します。 クラスコード:
<?php class ServiceUserIdentity extends UserIdentity { const ERROR_NOT_AUTHENTICATED = 3; /** * @var EAuthServiceBase the authorization service instance. */ protected $service; /** * Constructor. * @param EAuthServiceBase $service the authorization service instance. */ public function __construct($service) { $this->service = $service; } /** * Authenticates a user based on {@link username}. * This method is required by {@link IUserIdentity}. * @return boolean whether authentication succeeds. */ public function authenticate() { if ($this->service->isAuthenticated) { $this->username = $this->service->getAttribute('name'); $this->setState('id', $this->service->id); $this->setState('name', $this->username); $this->setState('service', $this->service->serviceName); $this->errorCode = self::ERROR_NONE; } else { $this->errorCode = self::ERROR_NOT_AUTHENTICATED; } return !$this->errorCode; } }
標準プロバイダークラスは、
id
と
name
2つの属性を提供します。 さらに、各プロバイダーには独自の識別子があり、これは
serviceName
プロパティに含まれています。
ServiceUserIdentity
クラス
ServiceUserIdentity
は
ServiceUserIdentity
これらの属性を現在のユーザーのセッション(およびCookie)に格納します。
4.2 SiteContoller
編集
2番目のステップは、
`site/login`
を変更することです。 アクションの先頭に次のコードを追加します。
public function actionLogin() { $service = Yii::app()->request->getQuery('service'); if (isset($service)) { $authIdentity = Yii::app()->eauth->getIdentity($service); $authIdentity->redirectUrl = Yii::app()->user->returnUrl; $authIdentity->cancelUrl = $this->createAbsoluteUrl('site/login'); if ($authIdentity->authenticate()) { $identity = new ServiceUserIdentity($authIdentity); // if ($identity->authenticate()) { Yii::app()->user->login($identity); // popup $authIdentity->redirect(); } else { // popup cancelUrl $authIdentity->cancel(); } } // - , $this->redirect(array('site/login')); } // ... }
最初に、変数
$_GET['service']
の存在を確認します。 そのような変数が存在する場合、プロバイダークラスのインスタンスを作成し、リダイレクトおよび承認の取り消しのパスを構成します。 次に、
`$authIdentity->authenticate()`
メソッドを呼び出します。このメソッドはすべての魔法を実行します。 メソッド
`$authIdentity->redirect();`
および
`$authIdentity->cancel();`
、使用する場合、ポップアップウィンドウを正しく閉じるために必要です。
4.3ビュー`protected/views/site/login.php`
標準ウィジェットを使用するには、メインフォームの後に数行追加するだけです。
<h2>Do you already have an account on one of these sites? Click the logo to log in with it here:</h2> <?php Yii::app()->eauth->renderWidget(); ?>
ウィジェットの外観を変更するには、ファイル
`protected/extensions/eauth/views/auth.php`
`[theme_name]/views/EAuthWidget/auth.php`
ます。
4.4結果
すべての手順が完了したら、Webサイトを開いてログインページに移動できます。 標準認証フォームの後に、認証サービスのアイコンが表示されます:
たとえば、Googleアイコンをクリックすると、ポップアップウィンドウが開きます。
ユーザーがアプリケーションの承認を確認すると、ユーザーはログインし、
redirectUrl
ページに
redirectUrl
ます(この例では
Yii::app()->user->returnUrl
)。 ユーザーが[
No, thanks
クリックすると、ポップアップウィンドウが閉じられます。
おわりに
以上で、認証システムは動作する準備が整いました。 拡張機能で他にできること:
- プロバイダーのクラスを展開して、ユーザーに関する追加情報を取得します。 Vkontakteによる認証中の例はデモにあります。
- 拡張機能をyii-userと統合します。 一般的に、ユーザーを登録するには、テーブル
{{users}}
2つのフィールド、service
とidentity
を追加するだけで十分です。 最初のフィールドは、許可サービスの名前(serviceName
プロパティー)です。 2番目は、このサービスのユーザーの一意の識別子(id
プロパティ)です。 - 拡張機能を使用して、ソーシャルネットワーキングAPIを操作します。
参照資料
更新: 「3.2設定」の項目に、ロイド拡張機能の欠如が追加されました。
更新2:現在のバージョンとセットアップ手順はgithub.comで入手できます。 この記事の手順は、EAuthバージョン<= 1.1.3に適しています。