在ASP.NET MVC 3会话Cookie到期处置,同时使用WIF和jQuery Ajax请求(S

2019-06-25 12:39发布

我在我的项目中,我使用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调用在执行时,该方法AuthenticateClaimsAuthenticationManager被调用。 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);
}

如何解决这一难题?

Answer 1:

我发现一些资源这个(看便知的底部),以及与下述溶液混合起来:

在执行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