【问题标题】:Session Cookies expiration handling in ASP.NET MVC 3 while using WIF and jquery ajax requests使用 WIF 和 jquery ajax 请求时 ASP.NET MVC 3 中的会话 Cookie 过期处理
【发布时间】:2012-06-18 11:10:27
【问题描述】:

我的项目我正在使用 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 调用时,将调用来自 ClaimsAuthenticationManager 的方法 AuthenticateIdentity.IsAuthenticated 返回 false,方法结束,一切都完成了。甚至 BaseController 中的 OnAuthorization 方法也没有被调用,所以我无法将任何状态传递给 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);
}

如何解决这个难题?

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-3 jquery session-cookies wif


    【解决方案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
            }
        });
    });
    

    更多解释请参见How to manage a redirect request after a jQuery Ajax call 和此处How do you deal with AJAX requests when user session expires, or where the request terminates in a 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() 和以前一样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-22
      • 2012-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-20
      • 2020-02-19
      • 2011-09-13
      相关资源
      最近更新 更多