20

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

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

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

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

4

4 回答 4

33

将 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 的博客中概述的一些技术,当您不想使用时防止表单身份验证登录页面重定向

于 2012-03-07T21:09:33.523 回答
1

您不必重写所有操作,只需创建一个自定义过滤器来替换内置Authorize过滤器。

其他人以前做过

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

于 2012-03-07T21:02:09.390 回答
0

您可以检查 Request.IsAjaxRequest() 扩展方法,如果为真,则采取特定操作。

于 2012-03-07T21:04:36.950 回答
0

Request.IsAjaxRequest()如果为真,您的 AccountController(或您拥有的任何地方)中的 LogOn 操作可能会返回不同的结果。

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

例如

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

    return View();
}

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

于 2012-03-07T21:41:35.590 回答