程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> yii2獲取登錄前的頁面url地址--電腦和微信浏覽器上的實現以及yii2相關源碼的學習,yii2url

yii2獲取登錄前的頁面url地址--電腦和微信浏覽器上的實現以及yii2相關源碼的學習,yii2url

編輯:關於PHP編程

yii2獲取登錄前的頁面url地址--電腦和微信浏覽器上的實現以及yii2相關源碼的學習,yii2url


對於一個有登錄限制(權限限制)的網站,用戶輸入身份驗證信息以後,驗證成功後跳轉到登錄前的頁面是一項很人性化的功能。那麼獲取登錄前的頁面地址就很關鍵,今天在做一個yii2項目的登錄調試時發現了一些很有意思的問題,記錄下來。

1,場景描述

網站SiteA上的頁面Page2需要登錄後才能查看,Page2的鏈接放在頁面Page1的一個按鈕Button上,Page1在登錄前後都是可以訪問的,SiteA只提供了微信掃碼登錄的入口。

2,功能需求

假定訪客User已經在SiteA上注冊過,但當前未登錄。User在浏覽Page1時,如果點擊頁面內的Button,則會來到掃碼登錄頁。用微信掃碼登錄成功後則會跳轉至Page2。

3,跳轉頁面的代碼

在微信授權後要回調的地址中設置好控制器controller和方法callback。

然後在callback方法中進行用戶登錄後的邏輯編寫,如果登錄成功:

return $this->goBack();

這麼寫在電腦的浏覽器上訪問網站時是沒有問題的,可以實現上述的功能需求。但是如果User是用手機在微信中訪問SiteA的Page1,然後點擊了Button,那麼他是不是會像在電腦上那樣來到Page2呢?

今天測試了下,沒有跳轉到Page2,反而來到了網站的首頁。至於原因是什麼,現在還不太清楚。不過倒是找到了解決的方法:在微信授權後要回調地址的地址中加上state參數,在state參數中附帶上User登錄前浏覽的頁面地址url。這樣在callback方法中就可以拿到url,上面登錄成功後的頁面跳轉就可以這麼寫:

1 if (strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') === false) {
2     // User在pc浏覽器中的跳轉
3     return $this->goBack();
4 } else {
5     // User在微信浏覽器中的跳轉
6     return $this->redirect(url);
7 }

4,User登錄前浏覽的頁面地址url該怎麼獲得

yii2中提供了一個方法,下面的方法就可以獲得登錄前的頁面url。

Yii::$app->user->returnUrl;

 

5,yii2是如何實現4中的方法和功能的呢?

4中的方法是在yii\web\User中定義的:

 1     public function getReturnUrl($defaultUrl = null)
 2     {
 3         $url = Yii::$app->getSession()->get($this->returnUrlParam, $defaultUrl);
 4         if (is_array($url)) {
 5             if (isset($url[0])) {
 6                 return Yii::$app->getUrlManager()->createUrl($url);
 7             } else {
 8                 $url = null;
 9             }
10         }
11 
12         return $url === null ? Yii::$app->getHomeUrl() : $url;
13     }

第3行yii\web\Session的get方法:

1     public function get($key, $defaultValue = null)
2     {
3         $this->open();
4         return isset($_SESSION[$key]) ? $_SESSION[$key] : $defaultValue;
5     }

可以看到yii2是從session中獲取的 $this->returnUrlParam 作為登錄前的浏覽頁面地址。

那麼它是如何存儲的session,又是在什麼時間存儲的呢?答案都在yii\web\User和yii\webSession中。

yii\web\User中的setReturnUrl()方法:

1     public function setReturnUrl($url)
2     {
3         Yii::$app->getSession()->set($this->returnUrlParam, $url);
4     }

 yii\web\User中的loginRequired()方法中調用了setReturnUrl()方法:

 1     public function loginRequired($checkAjax = true, $checkAcceptHeader = true)
 2     {
 3         $request = Yii::$app->getRequest();
 4         $canRedirect = !$checkAcceptHeader || $this->checkRedirectAcceptable();
 5         if ($this->enableSession
 6             && $request->getIsGet()
 7             && (!$checkAjax || !$request->getIsAjax())
 8             && $canRedirect
 9         ) {
10             $this->setReturnUrl($request->getUrl());
11         }
12         // ......省略的代碼
13     }

然後在yii\filters\AccessControl中的denyAccess()中又調用了loginRequired()

1     protected function denyAccess($user)
2     {
3         if ($user->getIsGuest()) {
4             $user->loginRequired();
5         } else {
6             throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
7         }
8     }

然後在yii\filters\AccessControl中的beforeAction()中又調用了denyAccess()。

AccessControl可以配置在控制器中,也可以配置在yii2應用的配置文件main.php中,如果配置了,那麼在每一次調用控制器的action之前都會執行這個beforeAction(),也就會觸發session的存儲。

yii\web\User中設置了默認要存儲的url鍵名

public $returnUrlParam = '__returnUrl';

可以看下session中的內容驗證下:

6,再來看下3中的$this->goBack()方法

yii\web\Contorller中

1     public function goBack($defaultUrl = null)
2     {
3         return Yii::$app->getResponse()->redirect(Yii::$app->getUser()->getReturnUrl($defaultUrl));
4     }

可以看到它也是跳轉到從 Yii::$app->getUser()->getReturnUrl() 獲取的url,其實也就是從session中獲取的url地址。

7,疑問

那麼上面的討論都是基於登錄操作(涉及到了登錄前後的邏輯),如果一個網站沒有登錄功能,也用不到權限控制(AccessControl),就更不用session存儲url了。嗯,應該是這麼回事。不用登錄操作的話,也就不會涉及到剛開始提到的頁面跳轉了。

 


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved