全面解析Yii2跨域的SSO登陸邏輯

來源:互聯網
上載者:User

簡述

本文章是我對Yii2如何?SSO登陸做一個全面的邏輯解析。事實上,在此之前我也寫過兩篇文章關於SSO登入的實現方式以及進一步最佳化,包括這篇文章也都是介紹Yii2的SSO登入,逐步最佳化不斷總結與分享,目的就是要把Yii2的SSO登入功能儘可能的做到極致,從程式開發的靈活性角度去思考問題,把一切潛在的局限扼殺在搖籃中。

實現步驟

1、在commonconfigmain.php檔案配置如下:

 [        '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、建立一個login模組,然後開啟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檔案MutilpleDomainUrlManager.php,這個檔案按照我給你們的命名空間存放。

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;    }}

注釋:用於擷取domain url。5、修改login模組下的SiteController.php Login方法

    //登入    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,                ]);            }        }    }

6、修改frontend模組下的SiteController.php Login方法

 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,                            ]);            }        }    }

7、在frontendviewsdefaultlayoutsmain.php的頂部加入下面代碼

$redirectURL='http://'.DOMAIN_LOGIN.'?redirectURL='.Yii::$app->request->getHostInfo().Yii::$app->request->url;

8、最後在退出的a標籤這麼輸出。

註:在其它模組如:backend、crm等等當中仿造我這frontend的實現思路改改,即可實現整個項目的SSO登入機制。

提醒注意

1、在第1步驟中,動態擷取無www的網域名稱,此步驟必須做網域名稱的判斷處理,比如: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步驟中的frontend模組下的SiteController.php Login方法裡,用Yii2內建的方法Yii::$app->request->getHostInfo().Yii::$app->user->getReturnUrl()擷取上一個url,這裡必須特別注意是擷取“上一個url”而不是當前的url,擷取當前的url就變成了login.xxx.com了,這是不對的。

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.