授權過期后AJAX操作跳轉到登錄頁的一種全局處理方式


前兩天園友JustRun分享了一篇 《菜鳥程序員之Asp.net MVC Session過期異常的處理》博文,正好自己前段時間被安排處理過這個問題,發現JustRun的方法有一點點可優化的地方,就評論里提了一下思路。今天看到有園友好像沒明白我說的意思,所以就決定寫此博文簡單介紹一下,不太適合老鳥們觀看,權當是給新人寫的一點經驗分享。

什么問題

通常在對一些敏感數據進行操作前,都要進行身份認證。如果沒有通過認證,則重定向(跳轉)到登錄頁面。但這種服務端重定義的方式,對ajax請求卻沒有任何作用。本文就是給出一種全局處理方式,來解決這類問題。

如何解決

思路很簡單,就是當授權過期后,針對ajax請求返回一個特定的標識,然后前端通過識別該標識,來跳轉到登錄頁面。而且最好不用在每處ajax請求的代碼中都加上對這種標識判斷,即要能全局處理。所以目標就落在了jQuery.ajax的全局配置($.ajaxSetup)上了,通過查看API,發現statusCode參數用來做這件事再好不過了,而且重要的是,即使ajax代碼中禁用了全局配置(global:false),關於statusCode的配置都仍然有效(這點對我們之前項目中來說很重要,因為有很多的ajax都禁用了全局的遮罩效果)。

代碼演示

原理清楚了,代碼實現起來也就並不復雜了,首先在服務端需要針對ajax請求,返回特殊的標識。這里重寫了MVC自帶的授權模塊的HandleUnauthorizedRequest邏輯,未通過授權時,如果是ajax請求,則返回一個HttpStatusCode,這個值盡量不要與現有的HTTP狀態碼重復,我這里用的是499,然后將登錄頁的地址寫到響應流中(這里可以根據需要返回其他信息)。自定義的授權模塊代碼如下:

    public class WebAuthorizeAttribute : AuthorizeAttribute
    {
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.Result = new HttpStatusCodeResult(499);                   //盡量不要與現有的Http狀態碼沖突
                filterContext.HttpContext.Response.Write(FormsAuthentication.LoginUrl); //可以根據需要返回其他信息
            }
            else
            {
                base.HandleUnauthorizedRequest(filterContext);
            }
        }
    }

然后就是前端部分的處理了,前端使用$.ajaxSetupstatusCode參數來統一處理,在模板頁面中,寫入以下代碼:

    <script type="text/javascript">
        $.ajaxSetup({
            statusCode: {
                499: function (data) {
                    alert(data.responseText);
                    //window.location.href = data.responseText; 
                }
            }
        });
    </script>

好了,所有的代碼都完成了,下面進行簡單的測試一下,服務端寫了兩個Action(這兩個Action需要用上面寫的授權模塊),一個返回Time,一個返回Guid:

        [WebAuthorize]
        public ActionResult GetTime()
        {
            return Content(DateTime.Now.ToString());
        }

        [WebAuthorize]
        public ActionResult GetGuid()
        {
            return Content(Guid.NewGuid().ToString());
        }

頁面上寫了兩個ajax請求,分別請求以上兩個Action:

<input id="Button1" type="button" value="GetTime" />
<input id="Button2" type="button" value="GetGuid" />
<script type="text/javascript">
    $("#Button1").click(function () {
        $.get("/Home/GetTime", function (data) {
            $("body").append(data + '<br/>');
        });
    });
    $("#Button2").click(function () {
        $.ajax({
            url: '/Home/GetGuid',
            global: false,  //禁用全局,不影響$.ajaxSetup中的statusCode
            success: function (data) { $("body").append(data + '<br/>'); }
        });
    });
</script>

當然還要添加登錄退出功能(這塊代碼就不貼了,見源碼吧),在授權有效期內,運行效果如下:

這時,如果我們再打開一個新頁面點退出(或直接把cookie刪掉),再點擊上面的GetTime或GetGuid按鈕發送ajax請求,結果如下:

OK,達到預期效果。如有更優雅的處理方式,也請大家分享。DEMO使用VS2010+MVC3開發,源碼請點此下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM