我在我的项目中,我使用WIF(但这不是这个问题的背景下非常重要的。您可以使用替代的框架,处理您的身份验证。问题是关于认证错误的处理,同时执行Ajax请求)。 从继承然而,在我来说,我已经写了自定义服务器逻辑ClaimsAuthenticationManager
,并处理身份验证:
public override IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal)
{
if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated)
{
// add some custom claims
}
return incomingPrincipal;
}
现在,当我删除所有会话Cookie,结束然后再输入任何页面,我重定向到WIF服务的登录页面,而且我要求重新登录。 一切正常。
但是,如果我做一个Ajax请求 ,而不是,我有一个错误,这是由该截获:
$(document).ready(function () {
$.ajaxSetup({
error: function (XMLHttpRequest, textStatus, errorThrown) {
// do something
}
});
});
不幸XMLHttpRequest
对象不返回任何有意义的信息,在此基础上,我可以处理这种错误的任何其他方式等。 在这种特殊情况下我只想应用重定向到登录页面 - 作为正常的要求做。
虽然AJAX调用在执行时,该方法Authenticate
从ClaimsAuthenticationManager
被调用。 Identity.IsAuthenticated
返回false,方法结束,一切都过去了。 即使是OnAuthorization
从方法BaseController
不调用,所以无法任何状态传递到AJAX结果对象。
protected override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest() && !User.Identity.IsAuthenticated)
{
//do something, for example pass custom result to filterContext
}
base.OnAuthorization(filterContext);
}
如何解决这一难题?
我发现一些资源这个(看便知的底部),以及与下述溶液混合起来:
在执行Ajax请求,我指定我想回JSON:
$.ajax({
url: action,
type: 'POST',
dataType: 'json',
data: jsonString,
contentType: 'application/json; charset=utf-8',
success:
function (result, textStatus, xhr) {
}
});
因为我的框架处理认证,而令牌到期,它把HTTP状态302的响应。 因为我不希望我的浏览器透明地处理302响应,我抓住它在Global.asax中,并改变状态到200 OK。 的方法,另外,我添加标题,指示我来处理特殊的方式这样回应:
protected void Application_EndRequest()
{
if (Context.Response.StatusCode == 302
&& (new HttpContextWrapper(Context)).Request.IsAjaxRequest())
{
Context.Response.StatusCode = 200;
Context.Response.AddHeader("REQUIRES_AUTH", "1");
}
}
响应内容不正确序列化到JSON,这将导致解析错误。 错误事件被调用时,在其内部进行重定向:
$(document).ready(function () {
$.ajaxSetup({
error: function (XMLHttpRequest, textStatus, errorThrown) {
if (XMLHttpRequest.getResponseHeader('REQUIRES_AUTH') === '1') {
// redirect to logon page
window.location = XMLHttpRequest.getResponseHeader('location');
}
// do sth else
}
});
});
请参阅如何管理一个jQuery Ajax调用后的重定向请求,并在这里当用户会话过期你如何处理与AJAX请求,或要求在302结束了更多的解释。
更新:
与此同时,我想通了新的解决方案,在我看来好得多 ,因为可以适用于所有Ajax请求开箱即用(如果他们不明显重新beforeSend事件):
$.ajaxSetup({
beforeSend: checkPulse,
error: function (XMLHttpRequest, textStatus, errorThrown) {
document.open();
document.write(XMLHttpRequest.responseText);
document.close();
}
});
function checkPulse(XMLHttpRequest) {
var location = window.location.href;
$.ajax({
url: "/Controller/CheckPulse",
type: 'GET',
async: false,
beforeSend: null,
success:
function (result, textStatus, xhr) {
if (xhr.getResponseHeader('REQUIRES_AUTH') === '1') {
XMLHttpRequest.abort(); // terminate further ajax execution
window.location = location;
}
}
});
}
控制器方法可以是任何简单的:
[Authorize]
public virtual void CheckPulse() {}
该Application_EndRequest()
保持和以前一样。
文章来源: Session Cookies expiration handling in ASP.NET MVC 3 while using WIF and jquery ajax requests