0

在我的 ASP.Net MVC 应用程序中,如果用户在 ajax 调用期间注销或会话超时,则登录页面将作为 html 返回到调用 javascript ajax 调用。这会导致客户端出错,因为它无法解析 html。

我想覆盖handleunauthorizedrequestonauthorize属性,但即使在覆盖它之后,调试时也不会被命中,并且仍然返回登录页面。

如果请求是 ajax 请求并且请求未经授权,我的目标是返回401状态代码。

这个问题的解决方案是什么,我仍然无法理解为什么handleunauthorizedrequest不被击中,不是被覆盖了吗?

4

4 回答 4

1

jquery ajax 中的 jqXhr 对象有一个 state 属性,可以像这样访问:

 jqXhr.state()

如果 state 属性的值为“rejected”,则表示未返回 json 结果并且您的呼叫被拒绝。

我使用此属性的值来确定会话是否已超时,并且我能够优雅地重定向到登录页面。

于 2013-05-11T23:09:51.627 回答
0

Default AuthorizeAttribute 不处理 AjaxRequest。您需要编写自己的实现。我在下面给出了一个示例实现,您可以根据需要进行自定义。

我在 homecontroller 中添加了一个操作来返回一个 JsonResult 并应用了默认的 [Authorize] 属性。

    [Authorize]
    public ActionResult SayHello()
    {
        object result=new {status="200",res="Hello"};
        return Json(result, JsonRequestBehavior.AllowGet);
    }

在视图中,我添加了一个简单的 ajax 事件来调用操作并将 res 显示为警报。

    <h3>
    <a id="anchorSayHello">Say Hello</a>
</h3>
@section Scripts{
    <script>
        $('#anchorSayHello').click(function () {
            $.ajax('/Home/SayHello', {
                success: function(data) {
                    var str = data.res;
                    alert(str);
                }
            });
            return false;
        });
    </script>

}

如您所说,它将返回一个未授权的 html 响应。

在此处输入图像描述

现在,让我们实现自定义 Authorize 属性并应用于操作

 public class TestAuthorize : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
        {
            object res = new { status = "404", redirect = "/Account/Login" };
            filterContext.Result = new JsonResult() { Data = res, JsonRequestBehavior = JsonRequestBehavior.AllowGet };

            return;
        }
        base.HandleUnauthorizedRequest(filterContext);
    }
}

现在让我们将Javascript修改为,

$('#anchorSayHello').click(function () {
            $.ajax('/Home/SayHello', {
                success: function (data) {
                    if (data.status === '200') {
                        var str = data.res;
                        alert(str);
                    } else {
                        window.location = data.redirect;
                    }
                }
            });
            return false;
        });

现在它应该可以按预期工作了,对于 ajax 请求,它也会重定向到登录页面。

在此处输入图像描述

于 2013-05-11T20:19:30.800 回答
0

以下应该工作。

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        var request = filterContext.HttpContext.Request;
        var response = filterContext.HttpContext.Response;
        if (request.IsAjaxRequest())
        {
            response.StatusCode = 401;
            filterContext.Result = new EmptyResult();
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

然后在控制器或动作中使用过滤器作为

//instead of Authorize
[CustomAuthorize]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

并在客户端添加一个钩子到ajaxError事件并检查状态码401

$(function(){
    $(document).ajaxError(function (e, xhr, opts) {
        if (401 == xhr.status) {
            //do whatever you like
            //return document.location = document.location;
        }
    });
});

希望这可以帮助。

于 2013-05-11T20:12:23.477 回答
0

从 .NET 4.5 开始,正确的答案是设置HttpResponse[Base].SuppressFormsAuthenticationRedirect为 true:

if (!httpContext.Request.IsAuthenticated)
{
    if (httpContext.Request.IsAjaxRequest())
    {
        httpContext.Response.SuppressFormsAuthenticationRedirect = true;
    }
    return new HttpUnauthorizedResult();
}
于 2013-10-18T00:56:12.327 回答