未经授权导致ajax请求

时间:2012-03-07 20:57:08

标签: jquery asp.net-mvc asp.net-mvc-3 http-status-code-401 unauthorized

我有许多ajax动作的应用程序(使用JQuery.ajax实现),它返回JSON或html。其中一些应该只有授权用户才能访问,我用[Authorize]属性修饰它们。对于非ajax操作,如果用户未被授权 - 系统将其重定向到登录页面(在web.config中配置)。

但是这不适用于ajax操作,因为如果用户被授权 - 他加载页面,在cookie过期后他没有被授权,而不是html块,那应该替换旧,他得到我的登录页面内。

我知道我可以手动解决这个问题,例如删除[Authorize]属性,如果用户没有授权,则返回特殊的json / empty html。但我不喜欢这个解决方案,因为我需要重写我的所有动作和ajax函数。我想要全局解决方案,允许我不要重写我的操作(可能是自定义授权属性,或某些http未经授权的结果自定义处理)。

如果请求是ajax,我想返回状态代码,如果请求不是ajax,则返回登录页面。

4 个答案:

答案 0 :(得分:31)

将Application_EndRequest处理程序添加到global.asax.cs中的代码中,该处理程序将任何302错误(重定向到登录页面)修改为AJAX请求的401(未授权)错误。这将允许您简单地保持控制器的操作,并通过客户端处理重定向(您实际上只能让用户再次登录)。

protected void Application_EndRequest()
{
    // Any AJAX request that ends in a redirect should get mapped to an unauthorized request
    // since it should only happen when the request is not authorized and gets automatically
    // redirected to the login page.
    var context = new HttpContextWrapper( Context );
    if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest())
    {
        context.Response.Clear();
        Context.Response.StatusCode = 401;
    }
}

然后在你的_Layout.cshtml文件中添加一个全局AJAX错误处理程序,当它获得401响应时重定向到你的登录操作。

<script type="text/javascript">
    $(function () {
        $(document).ajaxError(function (e, xhr, settings) {
            if (xhr.status == 401) {
                location = '@Url.Action( "login", "account" )';
            }
        });
    });
</script>

您可能还想尝试一下Phil Haack博客中列出的一些技巧,Prevent Forms Authentication Login Page Redirect When You Don’t Want It

答案 1 :(得分:1)

您无需重写所有操作,只需创建自定义过滤器即可替换内置Authorize过滤器。

其他人之前已经做过

asp.net mvc [handleerror] [authorize] with JsonResult?

答案 2 :(得分:0)

您可以检查Request.IsAjaxRequest()扩展方法,并在其为真时采取特定操作。

答案 3 :(得分:0)

如果Request.IsAjaxRequest()为真,也许你的AccountController中的LogOn操作(或者你拥有它的任何地方)都会返回不同的结果。

这意味着如果对授权操作的AJAX调用未通过授权,您应该能够通过LogOn操作返回适当的响应。

e.g。

public ActionResult LogOn()
{
    if (Request.IsAjaxRequest())
    {
        // do appropriate response for ajax call here
    }

    return View();
}

然后,您不需要进行重大改写