在ASP.NET MVC 3会话Cookie到期处理,而使用WIF和jQuery Ajax请求 [英] Session Cookies expiration handling in ASP.NET MVC 3 while using WIF and jquery ajax requests

查看:174
本文介绍了在ASP.NET MVC 3会话Cookie到期处理,而使用WIF和jQuery Ajax请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的项目,我使用WIF的(但这不是对这个问题的背景下非常重要的。你可以用另一种框架,处理您的身份验证。问题是关于与身份验证失败处理,同时执行Ajax请求) 的。

I my project I'm using WIF (but this is not really important for the context of this question. You can use alternative framework which handles your authentication. Question is about dealing with authentication failures while performing ajax requests). Nevertheless, in my case I've written custom server logic which inherits from ClaimsAuthenticationManager, and handles authentication:

public override IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal)
{
    if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated)
    {
        // add some custom claims
    }
    return incomingPrincipal;
}

现在,当我删除所有的会话Cookie ,结束然后再进入任何页面,我重定向到WIF服务的登录页面,而且我要求重新登录。一切正常。

Now, after I delete all Session Cookies, end then enter any page again, I'm redirected to the login page served by WIF, and I'm requested to log again. Everything works as expected.

但是,如果我做出的 Ajax请求而不是,我有一个错误,这是由该截获:

But if I make an ajax request instead, I've got an error, which is intercepted by this:

$(document).ready(function () {
    $.ajaxSetup({
        error: function (XMLHttpRequest, textStatus, errorThrown) {            
            // do something
        }
    });
});

不幸的是 XMLHtt prequest 对象不返回任何有意义的信息,在此基础上,我可以处理这种类型的错误以任何其他方式和别人一样。在这种特殊情况下我只想应用重定向到登录页面 - 作为正常请求确实

Unfortunately XMLHttpRequest object does not return any meaningful message, based on which I could handle this kind of error in any other way as others. In this particular case I just want application to redirect to the login page - as the normal request does.

虽然Ajax调用执行,从 ClaimsAuthenticationManager 方法身份验证被调用。 Identity.IsAuthenticated 返回false,方法结束,一切都过去了。从 BaseController 则不会调用,所以我不能传递到AJAX结果对象的状态。 OnAuthorization 方法p>

While the ajax call is executing, the method Authenticate from ClaimsAuthenticationManager is invoked. Identity.IsAuthenticated returns false, method ends and all is done. Even the OnAuthorization method from BaseController is not invoked, so I cannot pass any status to the ajax result object.

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);
}

如何解决这一难题?

How to resolve the puzzle ?

推荐答案

我发现一些资源这个(看便知的底部),并用以下解决方案混合起来:

I've found some resources about this (see bottom of the answer), and mixed up with following solution:

在执行Ajax请求,我指定我想回JSON:

while performing ajax request, I specified that I want json back:

$.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。的方法,另外,我添加标题,指示我来处理特殊的方式这样的回应:

Because my framework handles authentication, while token expires, it puts http status 302 to the response. Because I don't want my browser to handle 302 response transparently, I catch it in Global.asax, and changed status to 200 OK. Aditionally, I've added header, which instructs me to process such response in special way:

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,这导致分析错误。错误事件被调用,在其内部进行重定向:

Response content is not properly serialized to json, which results in parsing error. Error event is invoked, inside which the redirection is performed:

$(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
        }
    });
});

请参阅How jQuery的Ajax调用后管理一个重定向请求,并在这里<一个href=\"http://stackoverflow.com/questions/6324590/how-do-you-deal-with-ajax-requests-when-user-session-expires-or-where-the-reque\">How你处​​理AJAX请求时,用户会话过期,或者要求终止于302 更多的解释。

See How to manage a redirect request after a jQuery Ajax call and here How do you deal with AJAX requests when user session expires, or where the request terminates in a 302 for more explanation.

更新:

同时,我想通了新的解决方案,在我看来好得多,因为可以适用于所有的Ajax请求的开箱即用(如果他们不明显重新定义beforeSend事件):

Meantime, I figured out new solution, in my opinion much better, because can be applied to all ajax requests out of the box (if they do not redefine beforeSend event obviously):

$.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;
                }
            }
    });
}

该控制器的方法可以是任何简单的:

The controller method can be anything simplest:

[Authorize]
public virtual void CheckPulse() {}

Application_EndRequest()保持和以前一样。

这篇关于在ASP.NET MVC 3会话Cookie到期处理,而使用WIF和jQuery Ajax请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆