关于Yii2怎样完成跨域的SSO登录的剖析

序文

近年来收集生长很快,介入网购的人越来越多,然则人人在网购的时刻不知到有没有注重到无论是淘宝照样京东,他们用的都是二级域名,登录一个URL,登录胜利后又是一个URL,作为一个开发者横竖我是注重到了。

比方,淘宝登录的URL:https://login.taobao.com/memb…,登录胜利的URL:https://www.taobao.com/?spm=a…

也许人人能够以为是过剩,我一个URL就能够搞定,为何要整那末多个呢?贫苦。。。

人人能够设想一下,假如不把这两个模块星散的话,假如几千人,几万人,以至上亿人同时登录的话,你就这么个服务器那不得崩了。所以思索怎样完成这类跨域的SSO登录就显得尤为重要了。

需求剖析

1、进入登录页面的URL地点:login.XXX.com
2、登录胜利后跳转的URL地点:www.XXX.com
下面我主假如以Yii2框架为例说明注解一下我是怎样完成这类逾越的SSO登录的。

代码剖析

连系需求,散布实行:

1、新建一个名为login的模块
把backend拷贝一份出来,改文件夹的称号为login,文件夹的称号改了人人可别忘了也把里边的文件的定名空间改一下,要不会找不到定名空间。关于过剩的文件就把他删除了,免得占内存。至于删除啥保存啥的,就不详述了,由于这不是本文的重点,我这么跟你说吧,你需要用的就保存,不需要的统统删除。

2、写入设置信息
2.1、在commonconfig顶部加上domain信息,设置以下代码:

 $host_array = explode('.', $_SERVER["HTTP_HOST"]);
    if (count($host_array) == 3) {
        define('DOMAIN', $host_array[1] . '.' . $host_array[2]);
    }
    //针对com.cn域名
    elseif (count($host_array) == 4) {
        define('DOMAIN', $host_array[1] . '.' . $host_array[2]. '.' . $host_array[3]);
    }else{
        //echo "本系统不支持当地接见,请设置域名";exit;
    }
    
    // echo 'www.' . DOMAIN;exit;
    define('DOMAIN_HOME', 'www.' . DOMAIN);
    
    // define('DOMAIN_API', 'api.' . DOMAIN);
    define('DOMAIN_LOGIN', 'login.' . DOMAIN);
    // define('DOMAIN_IMG', 'img.' . DOMAIN);

然后在components里设置User 和 Session:

'user' => [            
            'identityClass' => 'login\models\User',
            'enableAutoLogin' => true,
            'identityCookie' => ['name' => '_identity', 'httpOnly' => true,'domain' => '.' . DOMAIN],
            // 'returnUrl'=>'//' . DOMAIN_HOME,
        ],        
'session' => [           
            'cookieParams' => ['domain' => '.' . DOMAIN, 'lifetime' => 0],            
            'timeout' => 3600,
        ],

以上设置完了以后,翻开commonconfigbootstrap.php加下这么一段代码:

Yii::setAlias('login', dirname(dirname(__DIR__)) . '/login'); //增添自定义目次构造

2.2、在loginconfig里修正 urlManager,改成下面这模样:

'urlManager' => [
                'class' => 'common\components\MutilpleDomainUrlManager',
                'domains' => [
                    'backend' => '//' . DOMAIN_BACKEND,
                    // 'mail' => '//' . DOMAIN_EMAIL,
                    // 'img' => '//' . DOMAIN_IMG,
                    // 'api' => '//' . DOMAIN_API,
                    'login' => '//' . DOMAIN_LOGIN,
                ],
                // 'baseUrl' => '//' . DOMAIN_HOME,   # Default BaseUrl
                'showScriptName' => false,
                'enablePrettyUrl' => true,  //美化URL
                'enableStrictParsing' => true, //设置有没有‘s’;  
                // 'suffix' => ".php",  
                'rules' => [ '' => 'site/login', // 假如没有这里,则接见域名不能直接翻开默许Action (去除URL的“site/login”) 
                ]   
       ],

3、新建一个MutilpleDomainUrlManager.php文件
MutilpleDomainUrlManager.php,这个文件根据我给你们的定名空间寄存。

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

附:如许我们能够运用以下代码天生别的domain url

Yii::$app->urlManager->createUrl('site/index'),   # www.xxx.com/site/index
Yii::$app->urlManager->createUrl('login', 'site/login'),  #  login.xxx.com/site/login
Yii::$app->urlManager->createUrl('article/list'),  #  login.xxx.com/article/list
Yii::$app->urlManager->createUrl('man', 'user/view'),  #  man.xxx.com/user/view

4、修正SiteController.php的Login要领
4.1、login模块

 login\controllers\SiteController.php

     public function actionLogin()
        {   
            $URL=Yii::$app->request->get('redirectURL');  
            $model = new LoginForm();
            //推断是不是已登录,非为上岸
            if (!\Yii::$app->user->isGuest) { 
                $this->actionLogout();//强制性退出
                return $this->redirect('http://'.DOMAIN_LOGIN.'?redirectURL=http://'.DOMAIN_HOME);
            } 
        
            if ($model->load(Yii::$app->request->post()) && $model->login()) {
                if(empty($URL)){
                    return $this->redirect('http://'.DOMAIN_HOME,301);
                }else{
                    return $this->redirect($URL,301);
                }           
                // return $this->goBack();
            } else { 
                return $this->renderPartial('login', [
                    'model' => $model,
                ]);
            }
        }
        

4.2、frontend模块

frontend\controllers\SiteController.php
      public function actionLogin()
    {   
        $URL=Yii::$app->request->get('redirectURL'); 
         //推断是不是已登录,非为上岸
        if (!\Yii::$app->user->isGuest) {
            // return $this->goHome();
            $this->actionLogout();//强制性退出
            return $this->redirect('http://'.DOMAIN_LOGIN.'?redirectURL=http://'.DOMAIN_HOME);
        }
        $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=http://'.DOMAIN_HOME);
            }else{
                return $this->renderPartial('login', [
                                'model' => $model,
                            ]);
            }
            
        }
    }

5、视图衬着
5.1在frontendviewslayoutsmain.php的顶部到场红框的代码
《关于Yii2怎样完成跨域的SSO登录的剖析》

5.2、末了在退出的a标签这么输出<?php echo $redirectURL; ?>。

OK,到这里就悉数完成了,这时刻人人能够测试一下,你会惊异的发明Yii2跨域的SSO登录已完成了。哈哈。。。

常见题目

1、手动输入login.XXX.com进入登录页面胜利了,封闭浏览器后,再从新翻开,地点栏输入www.XXX.com照样登录状况。

处理体式格局:
在login的要领里边的考证是不是已登录挪用“ $this->actionLogout()”退出要领,然后给他个重定向的URL,如:return $this->redirect(‘http://‘.DOMAIN_LOGIN.’?redirectURL=http://‘.DOMAIN_ADMIN),如许就能够防备你在地点栏输入login.XXX.com进入到登录页面了还退出不胜利的题目。

     参考代码:
         //推断是不是已登录,非为上岸
         if (!\Yii::$app->user->isGuest) { 
                        $this->actionLogout();//强制性退出
                        return $this->redirect('http://'.DOMAIN_LOGIN.'?redirectURL=http://'.DOMAIN_ADMIN);
                    } 

2、运用Yii::$app->urlManager->createUrl(‘login’, ‘site/login’)这类体式格局天生
domain url在视图没法天生的题目,原因是这类体式格局只能在控制器内里运用。

相干材料

Yii2 设置 跨域登录实例:http://www.kuitao8.com/201505…
Yii2 怎样应用redirect让页面自动跳转到外站?:https://segmentfault.com/q/10…

全文完,若有不足或许更好的体式格局要领,迎接人人积极提出,我们一同互相交流学习。

    原文作者:zacklee
    原文地址: https://segmentfault.com/a/1190000004650718
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞