当用AJAX请求一个资源时,服务器检查到认证过期,会重新返回302,通过HTTP抓包,是看到请求了登录页面的,但是JS是不会进行跳转到登录页面。

使用环境:

ASP.NET MVC 4

JQUERY EASY UI

 

待解决的问题

1,如果AJAX请求时认证实效,那么跳转到登录页面重新认证,然后才能进行其它操作。(必须解决)

2,在认证成功之后最好不要返回首页,然后用户又得重新进行进入刚才页面。

 

解决方法

后端

添加一个自定义的AuthorizeAttribute

实现原理:如果是AJAX请求,并且没有进行授权,那么就返回 HTTP 401,代码如下:

class MyAuth: AuthorizeAttribute
    { 
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest()
                && !filterContext.HttpContext.User.Identity.IsAuthenticated
                && (filterContext.ActionDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true).Any()
                    || filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(
                        typeof(AuthorizeAttribute),
                        true).Any()))
            {
                filterContext.HttpContext.SkipAuthorization = true;
                filterContext.HttpContext.Response.Clear();
                filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
                filterContext.Result = new HttpUnauthorizedResult("Unauthorized");
                filterContext.Result.ExecuteResult(filterContext.Controller.ControllerContext);
                filterContext.HttpContext.Response.End();
            }
            else base.OnAuthorization(filterContext);
        }
 
    }

前端

如果想让所有页面都能捕获401错误,那么就需要在模版页_Layout.cshtml中用JS进行判,代码如下:

null };
            var loginUrl = "/Login/Index?AJAX_Login=1";
             
            //... 
            $(document).ready(function() {
                $(document).ajaxError(function(event, jqxhr, settings) {
                    if (jqxhr.status == 401) { 
                            $("#dialog").prepend("<div id='LoginWindow' class='easyui-dialog' style='width:400px;height:300px;' closed='true' modal='true' title='再次认证'><iframe scrolling='auto' id='openXXXIframe' frameborder='0'  src='" + loginUrl + "' style='width:100%;height:100%;'></iframe></div>");
                            $.parser.parse('#dialog');
                            $('#LoginWindow').dialog('open');
                            lastAjaxCall.jqXHR = jqxhr;
                            lastAjaxCall.settings = settings; 
                    }
                });
            });

 

虽然现在实现了认证。

那么如何在登录页面认证成功之后自动把该窗口给关闭了?

因为是用iframe嵌套的登录页面,所以这个属性很重要“parent”

实现方式:

1,在_Layout.cshtml中再加一个JS方法,用于登录成功后的回调函数,代码如下:

function LoginSuccessCallBack() {
                $('#LoginWindow').dialog('close'); 
                $('#LoginWindow').empty();
                 
                if (lastAjaxCall.settings) {
                    $.ajax(lastAjaxCall.settings);
                    lastAjaxCall.settings = null;
                } 
            }

 

2,在Controller中获取传过来的参数:
            ViewBag.AJAX_Login = Request.QueryString["AJAX_Login"];
在VIEW中

如果认证成功,就调用LoginSuccessCallBack方法关闭窗口,在重新获取刚才没有请求成功的数据。

var ajaxLogin = '@ViewBag.AJAX_Login';
                            if (ajaxLogin == 1) {
                                parent.LoginSuccessCallBack(); 
                            } else {
                                window.location.href = "/Home/index";
                            }

参考:

http://www.cnblogs.com/dudu/p/3384234.html

http://stackoverflow.com/questions/2472578/is-it-possible-to-use-redirecttoaction-inside-a-custom-authorizeattribute-clas/2472878#2472878

http://stackoverflow.com/questions/2580596/how-do-you-handle-ajax-requests-when-user-is-not-authenticated

http://stackoverflow.com/questions/7532261/ajax-and-formsauthentication-how-prevent-formsauthentication-overrides-http-401/7628655#7628655

相关文章:

  • 2021-12-16
  • 2022-12-23
  • 2021-05-19
  • 2022-12-23
  • 2022-12-23
  • 2021-11-27
  • 2022-12-23
  • 2021-12-07
猜你喜欢
  • 2021-05-25
  • 2021-08-18
  • 2022-12-23
  • 2022-12-23
  • 2021-06-16
  • 2022-12-23
相关资源
相似解决方案