使用ASP.NET MVC的json请求的401响应代码


35

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

对于网页它没关系,但对于AJAX我需要得到正确的401错误代码,而不是漂亮的302/200登录页面。

更新: 有来自菲尔哈克,ASP.NET MVC的PM几种解决方案 - http://haacked.com/archive/2011/10/04/prevent-forms-authentication-login-page-redirect-when-you-donrsquot-want.aspx

18

的ASP.NET运行时开发,使其始终将用户重定向如果HttpResponse.StatusCode设置为401,但只有在Web.config的<authentication />部分找到。

卸下认证部将要求您在你的属性中实现重定向到登录页面,但是这个不应该是一个大问题。

  0

实现自己的重定向的最佳方法是子类AuthorizeAttribute,并且当未授权时将结果设置为RedirectResult而不是HttpUnauthorizedResult。 07 1月. 102010-01-07 15:44:45

+2

是的,但在这种情况下,OP希望发送HTTP代码401,但不会重定向(以便使用JSON正常工作)。 08 1月. 102010-01-08 20:34:45

  0

适用于我 - 尽管我将设置配置为<authentication mode =“None”/>,而不是完全删除属性。 15 6月. 132013-06-15 03:20:54

+3

嗯 - 除了我在MVC控制器中使用Forms身份验证,所以实际上这不适用于我。需要404 &&表单认证解决方案,而不是||。 18 6月. 132013-06-18 04:18:48

+1

如果您想要使用表单身份验证并拥有自定义401重定向,那该怎么修复? 29 8月. 132013-08-29 16:59:01

+2

@DevDave - 查看我的答案。 29 8月. 132013-08-29 22:52:34


1

你可以选择创建一个自定义FilterAttribute实现IAuthorizationFilter接口。

在此属性中添加逻辑以确定请求是否应返回JSON。如果是这样,您可以返回一个空的JSON结果(或者做任何你喜欢的事情),因为用户没有登录。对于其他响应,您只需重新定向用户。

更好的是,您可以覆盖AuthorizeAttribute类的OnAuthorization,因此您不必重新发明轮子。加入我上面和拦截提到如果filterContext.Cancel为true(filterContext.Result将被设置为HttpUnauthorizedResult类的一个实例的逻辑。

了解更多关于"Filters in ASP.NET MVC CodePlex Preview 4"菲尔Haacks博客,它也适用于最新的预览。

  0

但我仍然无法获得401响应状态码的AJAX请求。 即使我在Autorization过滤器中设置响应。由于捕获401响应和重定向到登录页面的ASP.NET基础结构位于ASP.NET MVC之上。让我们知道用户没有通过空的JSON结果记录是不是很正确... 24 9月. 082008-09-24 15:04:09

  0

我不明白到目前为止你的想法。我添加了一个可以解决您的问题的新答案。 24 9月. 082008-09-24 22:24:04

+1

你是如何设法发布两个答案的? :) 30 8月. 132013-08-30 09:13:50


2

你也可以使用在Global.asax中断这个过程,是这样的:

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

我这样做了,除了我在上面的@troethom的回答中检查了302和X-Requested-With。 09 9月. 102010-09-09 18:35:57


24

在经典ASP.NET调用与阿贾克斯一个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; 
    } 
} 
  0

如果您需要快速的工作,这是一个非常好的解决方案。否则,我会尝试实现@troethom的答案。 07 1月. 102010-01-07 15:44:04


8

我希望这两个表单身份验证,并返回一个未经过身份验证的Ajax请求401。

最后,我创建了一个自定义的AuthorizeAttribute并修饰了控制器方法。 (这是.NET 4.5)

//web.config

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

//控制器

[Authorize(Roles = "Administrator,User"), Response302to401] 
[AcceptVerbs("Get")] 
public async Task<JsonResult> GetDocuments() 
{ 
    string requestUri = User.Identity.Name.ToLower() + "/document"; 
    RequestKeyHttpClient<IEnumerable<DocumentModel>, string> client = 
     new RequestKeyHttpClient<IEnumerable<DocumentModel>, string>(requestUri); 

    var documents = await client.GetManyAsync<IEnumerable<DocumentModel>>(); 

    return Json(documents, JsonRequestBehavior.AllowGet); 
} 

// authorizeAttribute

public class Response302to401 : AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
     { 
      if (filterContext.HttpContext.Request.IsAjaxRequest()) 
      { 
       filterContext.Result = new JsonResult 
       { 
        Data = new { Message = "Your session has died a terrible and gruesome death" }, 
        JsonRequestBehavior = JsonRequestBehavior.AllowGet 
       }; 
       filterContext.HttpContext.Response.StatusCode = 401; 
       filterContext.HttpContext.Response.StatusDescription = "Humans and robots must authenticate"; 
       filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true; 
      } 
     } 
     //base.HandleUnauthorizedRequest(filterContext); 
    } 
} 
  0

如果我想要使用标准表单授权重定向,当用户没有登录时该怎么办?但是如果用户没有相关权限,任何想法,还要调用自定义401重定向? 30 8月. 132013-08-30 11:41:59

  0

您将在没有此AuthorizeAttribute的方法上获得正常表单重定向。您也可以通过提供if(!filterContext.IsAuthenticated)的“else”子句来扩展该属性,在该子句中您将检查权限,然后自行设置重定向。 30 8月. 132013-08-30 18:42:13


2

我看不出有什么我们必须修改认证模式或认证标签,就像当前的答案所述。

继@ @ TimothyLeeRussell的想法(谢谢你),我创建了一个自定义的Authorize属性(@TimothyLeeRussell的问题是抛出一个异常,因为他试图改变filterContext.Result并生成一个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); 
    } 
} 
+1

SuppressFormsAuthenticationRedirect属性正是我所需要的。 14 7月. 152015-07-14 12:04:02


1

你可以叫你的动作在此方法中,

HttpContext.Response.End(); 

public async Task<JsonResult> Return401() 
{ 
    HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; 
    HttpContext.Response.End(); 
    return Json("Unauthorized", JsonRequestBehavior.AllowGet); 
} 

MSDN:End方法使Web服务器停止处理脚本并返回当前结果。该文件的其余内容不被处理。