当用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