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

来源:http://www.cnblogs.com/yangtoude/archive/2016/12/12/yii2-redirect-to-previous-url-after-login-on-pc-and-wechat.html
-Advertisement-
Play Games

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


對於一個有登錄限制(許可權限制)的網站,用戶輸入身份驗證信息以後,驗證成功後跳轉到登錄前的頁面是一項很人性化的功能。那麼獲取登錄前的頁面地址就很關鍵,今天在做一個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中的內容驗證下:

__returnUrl|s:29:"/controller/action?id=value";

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了。嗯,應該是這麼回事。不用登錄操作的話,也就不會涉及到剛開始提到的頁面跳轉了。

 


 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 所有 ReSherper 的功能都可以使用快捷鍵。大部分功能都有預設快捷鍵,剩下的少數功能可以自定義快捷鍵。 ReSharper 提供了兩種快捷鍵的方式 Visual Studio:這種方式可以減少與 Visual Studio 本身快捷鍵的衝突。 ReSharper 2.0/IntelliJ ID ...
  • 一.昨天內容回顧 a) 主流瀏覽器 new XMLHttpRequest(); b) IE瀏覽器 new ActiveXObject(“Msxml2.XMLHTTP.6.0”); 屬性:responseText/responseXML readyState onreadystatechange 方法 ...
  • 線程通信: 如果線程A和線程B持有同一個MyObject類的對象object,這兩個線程會去調用不同的方法,但是它們是同步執行的,比如:線程B需要等待線程A執行完了methodA()方法之後,它才能執行methodB()方法。這樣,線程A和線程B就實現了 通信。 線程通信中要用到的方法:wait() ...
  • 驗證碼功能(個人理解): 個人思路:在a-z,A-Z,1-9生成n位隨機的數來構成新的驗證碼。 關於生成驗證碼的幾個小函數 a) 如: range(1,9) a) array_merge(數組1,數組2….) a) 隨機從數組中取出幾個下標返回一個數組 生成驗證碼代碼 <?php $arr1=ran ...
  • A new built-in function, enumerate() , will make certain loops a bit clearer. enumerate(thing) , where thing is either an iterator or a sequence, retu ...
  • 準備篇: 1、配置防火牆,開啟80埠、3306埠 vi /etc/sysconfig/iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT(允許80埠通過防火牆) -A INPUT -m state ...
  • 第一篇博客。 克魯斯卡爾求最小生成樹思想:首先將n個點看做n個獨立的集合,將所有邊快排(從小到大)。然後,按排好的順序枚舉每一條邊,判斷這條邊連接的兩個點是否屬於一個集合。若是,則將這條邊加入最小生成樹,並將兩個點所在的集合合併為一個集合。若否,則跳過。直到找到n-1條邊為止。 #include<i ...
  • 這個系統是南方七星彩投註網站系統源碼,網站是採用php+MySQL的。基本實現功能如下:這個是普通的七星前四位的網投註平臺股東-總代理-代理-會員 這四個級別 網站大家只限於學習與交流,並且在合法的範圍使用,為了防止系統其他用戶,代碼有進行加密了,不便多多瞭解。 投註網站源碼附件: http://f ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...