我遇到了同样的问题,不得不在 MVC 中使用自定义属性。您可以轻松地将其调整为在 Web 表单中工作,如果您的所有页面都从某个基本页面继承(MVC 中的全局属性允许相同的事情 - 覆盖所有控制器/操作的 OnAuthorization 方法),则可以覆盖基本页面中页面的授权申请)
这是属性的样子:
public class AjaxAuthorizationAttribute : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest()
&& !filterContext.HttpContext.User.Identity.IsAuthenticated
&& (filterContext.ActionDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true).Count() > 0
|| filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true).Count() > 0))
{
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();
}
}
}
请注意,您需要调用 HttpContext.Response.End();否则您的请求将被重定向到登录(因此我失去了一些头发)。
在客户端,我使用了 jQuery ajaxError 方法:
var lastAjaxCall = { settings: null, jqXHR: null };
var loginUrl = "yourloginurl";
//...
//...
$(document).ready(function(){
$(document).ajaxError(function (event, jqxhr, settings) {
if (jqxhr.status == 401) {
if (loginUrl) {
$("body").prepend("<div class='loginoverlay'><div class='full'></div><div class='iframe'><iframe id='login' src='" + loginUrl + "'></iframe></div></div>");
$("div.loginoverlay").show();
lastAjaxCall.jqXHR = jqxhr;
lastAjaxCall.settings = settings;
}
}
}
}
这显示了在当前页面的 iframe 中登录(看起来用户被重定向但你可以让它不同),当登录成功时,这个弹出窗口被关闭,并重新发送原始 ajax 请求:
if (lastAjaxCall.settings) {
$.ajax(lastAjaxCall.settings);
lastAjaxCall.settings = null;
}
这允许您的用户在会话到期时登录,而不会丢失他们在最后显示的表单中输入的任何工作或数据。