前言:
当用AJAX请求一个资源时,服务器检查到认证过期,会重新返回302,通过HTTP抓包,是看到请求了登录页面的,但是JS是不会进行跳转到登录页面。
使用环境:
ASP.NET MVC 4
JQUERY EASY UI
待解决的问题
1,如果AJAX请求时认证实效,那么跳转到登录页面重新认证,然后才能进行其它操作。(必须解决)
2,在认证成功之后最好不要返回首页,然后用户又得重新进行进入刚才页面。
解决方法
后端
添加一个自定义的AuthorizeAttribute
实现原理:如果是AJAX请求,并且没有进行授权,那么就返回 HTTP 401,代码如下:

Code public 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进行判,代码如下:

Code var lastAjaxCall = { settings: null, jqXHR: 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方法,用于登录成功后的回调函数,代码如下:

Code 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方法关闭窗口,在重新获取刚才没有请求成功的数据。

Code 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2011-10-25 使用Kdiff3 来解决Git的文件冲突