Asp.net mvc 401使用ASP.NET MVC处理json请求的响应代码

Asp.net mvc 401使用ASP.NET MVC处理json请求的响应代码,asp.net-mvc,Asp.net Mvc,如何为AJAX/JSON请求禁用标准ASP.NET处理401响应代码(重定向到登录页面) 对于网页来说,这没关系,但对于AJAX,我需要获得正确的401错误代码,而不是用于登录页面的好看的302/200 更新: ASP.NET MVC的PM Phil Haack提供了几种解决方案-您可以选择创建自定义的FilterAttribute来实现IAuthorizationFilter接口 在这个属性中,您添加了逻辑来确定请求是否应该返回JSON。如果是这样,您可以返回一个空的JSON结果(或者执行任何

如何为AJAX/JSON请求禁用标准ASP.NET处理401响应代码(重定向到登录页面)

对于网页来说,这没关系,但对于AJAX,我需要获得正确的401错误代码,而不是用于登录页面的好看的302/200

更新
ASP.NET MVC的PM Phil Haack提供了几种解决方案-

您可以选择创建自定义的
FilterAttribute
来实现
IAuthorizationFilter
接口

在这个属性中,您添加了逻辑来确定请求是否应该返回JSON。如果是这样,您可以返回一个空的JSON结果(或者执行任何您喜欢的操作),前提是用户没有登录。对于其他响应,您将一如既往地重定向用户

更好的是,您可以覆盖
AuthorizeAttribute
类的
OnAuthorization
,这样就不必重新发明轮子了。添加我上面提到的逻辑,如果
filterContext.Cancel
为true,则进行拦截(
filterContext.Result
将设置为
HttpUnauthorizedResult
类的实例)


请阅读Phil Haacks博客上的更多信息。它也适用于最新预览。

ASP.NET运行时的开发是为了在
HttpResponse.StatusCode
设置为401时始终重定向用户,但只有在找到Web.config的
部分时


删除身份验证部分将要求您在属性中实现登录页面的重定向,但这并不是什么大问题。

您也可以使用Global.asax中断此过程,方法如下:

    protected void Application_PreSendRequestHeaders(object sender, EventArgs e) {
        if (Response.StatusCode == 401) {
            Response.Clear();
            Response.Redirect(Response.ApplyAppPathModifier("~/Login.aspx"));
            return;
        }
    }

在经典ASP.NET中,当使用Ajax调用WebMethod时,您会得到401 http响应代码。我希望他们会在ASP.NET MVC的未来版本中对其进行更改。现在我正在使用以下技巧:

protected void Application_EndRequest()
{
    if (Context.Response.StatusCode == 302 && Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
    {
        Context.Response.Clear();
        Context.Response.StatusCode = 401;
    }
}

我需要表单身份验证,并为未经身份验证的Ajax请求返回401

最后,我创建了一个自定义的AuthorizeAttribute并修饰了控制器方法

//web.config

<authentication mode="Forms">
</authentication>

我看不出有什么需要修改身份验证模式或身份验证标签,就像当前答案所说的那样

遵循@Timothylerussell的思想(顺便说一句,谢谢),我创建了一个定制的Authorize属性(@Timothylerussell的问题在于,抛出异常是因为他试图更改filterContext。生成HttpException的结果,并删除该部分,除了filterContext.HttpContext.Response.StatusCode=401外,响应代码始终为200 OK).因此,我最终通过在更改后结束响应来解决问题

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class BetterAuthorize : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            //Set the response status code to 500
            filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            filterContext.HttpContext.Response.StatusDescription = "Humans and robots must authenticate";
            filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;

            filterContext.HttpContext.Response.End();
        }
        else
            base.HandleUnauthorizedRequest(filterContext);
    }
}

您可以在操作中调用此方法

 HttpContext.Response.End();
范例

public async Task<JsonResult> Return401()
{
    HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
    HttpContext.Response.End();
    return Json("Unauthorized", JsonRequestBehavior.AllowGet);
}
public异步任务Return401()
{
HttpContext.Response.StatusCode=(int)HttpStatusCode.Unauthorized;
HttpContext.Response.End();
返回Json(“Unauthorized”,JsonRequestBehavior.AllowGet);
}

From:End方法导致Web服务器停止处理脚本并返回当前结果。文件的剩余内容未被处理。

但我仍然无法获取AJAX请求的401响应状态代码。即使我在自动化筛选器中设置了响应。因为ASP.NET基础设施可以捕获401响应和重定向登录页面位于ASP.NET MVC之上。让用户知道没有使用空JSON结果登录是不太正确的…直到现在我才完全理解您的想法。我正在添加一个新的答案来解决您的问题。如果您需要快速有效的解决方案,这是一个非常好的权宜之计。否则,我会尝试实现@troethom回答。实现您自己重定向的最佳方法是将AuthorizeAttribute子类化,当未授权时,将结果设置为RedirectResult,而不是HttpUnauthorizedResult。是的,但在这种情况下,OP希望发送HTTP代码401,但不发送重定向(以正确使用JSON).Um-除了我在MVC控制器中使用表单身份验证,所以实际上这对我不起作用。需要一个404&&Forms身份验证解决方案,而不是一个非此即彼的| | |。如果你想使用表单身份验证并自定义401重定向,有什么解决方案?@DevDave-请参阅我的答案。我这样做了,只是在a中检查了302和X-request-With来自上面@troetom的nswer。如果我想在用户未登录时使用标准表单授权重定向,但在用户没有相关权限时调用自定义401重定向,您有什么想法吗?您将在没有此authorized属性的方法上获得普通表单重定向。您也可以通过提供if(!filterContext.IsAuthenticated)的“else”子句,您可以在其中检查权限,然后自己设置重定向。SuppressFormsAuthenticationRedirect属性正是我想要的。
 HttpContext.Response.End();
public async Task<JsonResult> Return401()
{
    HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
    HttpContext.Response.End();
    return Json("Unauthorized", JsonRequestBehavior.AllowGet);
}