この記事は、Yii2 が SSO ログインを実装する方法についての包括的な論理分析です。実は、以前に SSO ログインの実装とさらなる最適化について 2 つの記事を書きましたが、この記事でも Yii2 の SSO ログインを紹介し、段階的に最適化し、継続的に Yii2 の SSO ログインを改善することを目的としています。機能は可能な限り完璧である必要があり、プログラム開発の柔軟性の観点から問題を検討し、潜在的な制限をすべて取り除きます。
1. commonconfigmain.php ファイルを次のように構成します。
<?php use kartik\mpdf\Pdf;//动态获取无www的域名$host_array = explode('.', $_SERVER["HTTP_HOST"]); if (count($host_array) == 3) { if(strpos($_SERVER["HTTP_HOST"],':')){ //判断域名是否存在端口号 $domain_array=explode(':', $host_array[2]); define('DOMAIN', $host_array[1] . '.' . $domain_array[0]);//去掉端口号,避免域名带端口号无法退出 }else{ define('DOMAIN', $host_array[1] . '.' . $host_array[2]); } }//针对com.cn域名elseif (count($host_array) == 4) { if(strpos($_SERVER["HTTP_HOST"],':')){ $domain_array=explode(':', $host_array[3]); define('DOMAIN', $host_array[1] . '.' . $host_array[2]. '.' . $domain_array[0]); }else{ define('DOMAIN', $host_array[1] . '.' . $host_array[2]. '.' . $host_array[3]); } }else{ //echo "本系统不支持本地访问,请配置域名";exit;}//将动态获取到的无www域名,配置上www、crm...define('DOMAIN_HOME', 'www.' . DOMAIN);define('DOMAIN_CRM', 'crm.' . DOMAIN);define('DOMAIN_HR', 'hr.' . DOMAIN);define('DOMAIN_WEIXIN', 'weixin.' . DOMAIN);define('DOMAIN_ADMIN', 'admin.' . DOMAIN);define('DOMAIN_OA', 'oa.' . DOMAIN);define('DOMAIN_FRONTEND', 'frontend.' . DOMAIN);define('DOMAIN_BACKEND', 'backend.' . DOMAIN);define('DOMAIN_API', 'api.' . DOMAIN);define('DOMAIN_LOGIN', 'login.' . DOMAIN);配置User 和 Session:'components' => [ 'user' => [ 'identityClass' => 'login\models\User', 'enableAutoLogin' => true, 'identityCookie' => ['name' => '_identity', 'httpOnly' => true,'domain' => '.' . DOMAIN], // 'returnUrl'=>'//' . DOMAIN_HOME, ], 'session' => [ 'cookieParams' => ['domain' => '.' . DOMAIN, 'lifetime' => 0], 'timeout' => 24*3600*30, ],
2. 新しいログイン モジュールを作成し、commonconfigbootstrap.php を開き、これを追加します。コード部分:
Yii::setAlias('login', dirname(dirname(__DIR__)) . '/login'); //增加自定义目录结构
3.loginconfigmain.php の urlManager を次のように変更します。
'urlManager' => [ 'class' => 'common\components\MutilpleDomainUrlManager', 'domains' => [ 'crm' => '//' . DOMAIN_CRM, 'admin' => '//' . DOMAIN_ADMIN, 'hr' => '//' . DOMAIN_HR, 'oa' => '//' . DOMAIN_OA, 'frontend' => '//' . DOMAIN_FRONTEND, 'backend' => '//' . DOMAIN_BACKEND, // 'img' => '//' . DOMAIN_IMG, 'api' => '//' . DOMAIN_API, 'login' => '//' . DOMAIN_LOGIN, ], //'baseUrl' => 'http://'.DOMAIN_LOGIN.'?redirectURL=http://'.DOMAIN_HOME, 'showScriptName' => false, 'enablePrettyUrl' => true, //美化URL 'enableStrictParsing' => true, //设置有无‘s’; // 'suffix' => ".php", 'rules' => [ '' => 'site/login', // 如果没有这里,则访问域名不能直接打开默认Action (去除URL的“site/login”) ] ],
4. ステップ 3 で不足している MutilpleDomainUrlManager.php ファイルを追加します。ファイルは、指定した名前空間に従って保存されます。
<?phpnamespace common\components; use Yii; class MutilpleDomainUrlManager extends \yii\web\UrlManager{ public $domains = array(); public function createUrl($domain, $params = array()) { if (func_num_args() === 1) { $params = $domain; $domain = false; } $bak = $this->getBaseUrl(); if ($domain) { if (!isset($this->domains[$domain])) { throw new \yii\base\InvalidConfigException('Please configure UrlManager of domain "' . $domain . '".'); } $this->setBaseUrl($this->domains[$domain]); } $url = parent::createUrl($params); $this->setBaseUrl($bak); return $url; }}
注: ドメイン URL を取得するために使用されます。 5. ログイン モジュール
//登录 public function actionLogin() { //获取当前的URL $URL=Yii::$app->request->getHostInfo().Yii::$app->request->url; $URL1='http://'.DOMAIN_CRM; $redirectURL=Yii::$app->request->get('redirectURL'); $redirectURL1='http://'.DOMAIN_LOGIN; $model = new LoginForm(); TagDependency::invalidate(Yii::$app->cache, ['Session:'.Yii::$app->session->id]); //验证是否已登录,非空为登录 if (!\Yii::$app->user->isGuest) { if(!empty($redirectURL)){ $this->actionLogout();//强制性退出登录 return $this->redirect($URL); }else{ //redirectURL不存在时,提交表单判断 if($this->siteLogin){ if ($model->load(Yii::$app->request->post()) && $model->login()) { //判断该账号是否禁止登录 if(empty($t_status=$model->user->attributes['t_status']) && $t_status==0){ return $this->error($redirectURL1,[Yii::t('yii','The account is prohibited from logging in, please contact the administrator!')]); }else{ if(empty($redirectURL)) return $this->redirect($URL1,301); return $this->redirect($redirectURL,301); } } else { return $this->renderPartial('login', [ 'model' => $model, ]); } }else{ return $this->goHome(); } } } else { //redirectURL存在时,提交表单判断 if ($model->load(Yii::$app->request->post()) && $model->login()) { //判断该账号是否禁止登录 if(empty($t_status=$model->user->attributes['t_status']) && $t_status==0){ if(empty($redirectURL)){ return $this->error($redirectURL1,[Yii::t('yii','The account is prohibited from logging in, please contact the administrator!')]); } return $this->error($URL,[Yii::t('yii','The account is prohibited from logging in, please contact the administrator!')]); }else{ if(empty($redirectURL)) return $this->redirect($URL1,301); return $this->redirect($redirectURL,301); } } else { return $this->renderPartial('login', [ 'model' => $model, ]); } } }
の下にある SiteController.php Login メソッドを変更します。 6. フロントエンド モジュール
public function actionLogin() { //获取上一个URL $URL=Yii::$app->request->getHostInfo().Yii::$app->user->getReturnUrl(); if (!\Yii::$app->user->isGuest) { return $this->redirect('http://'.DOMAIN_LOGIN.'?redirectURL='.$URL); } $model = new LoginForm(); if ($model->load(Yii::$app->request->post()) && $model->login()) { return $this->goBack(); } else { if(!empty($URL)){ return $this->redirect('http://'.DOMAIN_LOGIN.'?redirectURL='.$URL); }else{ return $this->renderPartial('login', [ 'model' => $model, ]); } } }
の下にある SiteController.php Login メソッドを変更します。 7. Frontendviewsdefaultlayoutsmain.php 次のコードを追加します
$redirectURL='http://'.DOMAIN_LOGIN.'?redirectURL='.Yii::$app->request->getHostInfo().Yii::$app->request->url;
8. 最後に、exit a タグに
注: バックエンド、crm などの他のモジュールで私のフロントエンド実装のアイデアを模倣することで、プロジェクト全体の SSO ログイン メカニズムを実現できます。
1. 最初のステップでは、www.xxx などのドメイン名を使用して動的にドメイン名を取得します。 com、www .xxx.com.cn、www.xxx.com:8099、およびその他の考えられるドメイン名を使用して、ドメイン名がログインおよび終了メカニズムを使用できることを確認します。
2. ステップ 5 と 7 では、Yii2 独自のメソッド Yii::$app->request->getHostInfo().Yii::$app->request- >url を使用します。 URL はより便利で効率的な方法であり、コードの冗長性を減らすことができます。
3. ステップ 6 のフロントエンド モジュールの SiteController.php Login メソッドで、Yii2 組み込みメソッド Yii::$app->request->getHostInfo().Yii:: $ を使用します。 app->user->getReturnUrl() は前の URL を取得します。現在の URL ではなく「前の URL」を取得することに特別な注意を払う必要があります。これは正しくありません。 。