始终使用HttpResponseMessage 401在ajax帖子上取得成功

Val*_*lin 8 c# ajax jquery httpresponse asp.net-web-api

我总是statusCode=200在客户端获得ajax帖子,而服务器则回答HttpStatusCode.Unauthorized.

我的控制器代码:

public class AccountApiController : ApiController
{
    public HttpResponseMessage Login(HttpRequestMessage request, [FromBody]LoginViewModel loginModel)
    {
        return request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Unauthorized login.");
    }
}
Run Code Online (Sandbox Code Playgroud)

我的ajax代码:

$.ajax({
    url: '/api/accountapi/login',
    type: 'POST',
    data: data
    })
    .done(function (object, status, xhr) {
        alert("Success: " + xhr.status + " : " + xhr.statusText);
    })
    .always(function (object) {
        $("#output").text(JSON.stringify(object, null, 4));
    });
Run Code Online (Sandbox Code Playgroud)

结果:带文本Success: 200 : OK 和输出窗口的警报:

{
    "Message": "Unauthorized login."
}
Run Code Online (Sandbox Code Playgroud)

所以,我可以得到文本错误消息,但我需要让HttpStatusCode来处理错误语句.请帮帮我.

有关此问题的更多信息以及来自Brock Allen的优雅解决方案:http: //brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/

joe*_*301 10

由于返回的状态为200,但用户未获得授权,因此另一个选项是在javascript中检查状态为401的X-Responded-JSON.

.done(function (object, status, xhr) {
      if (xhr.getResponseHeader("X-Responded-JSON") != null 
          && JSON.parse(xhr.getResponseHeader("X-Responded-JSON")).status == "401") {
          //some message here
          return;
     }
}
Run Code Online (Sandbox Code Playgroud)


Mag*_*dal 6

您可能会在返回后立即通过表单身份验证模块将页面重定向到登录页面HttpStatusCode.Unauthorized.

来自MSDN:

所有未经身份验证的用户都被拒绝访问您的应用程序中的任何页面.如果未经身份验证的用户尝试访问页面,则表单身份验证模块会将用户重定向到由forms元素的loginUrl属性指定的登录页面.

登录页面或其被重定向到的任何页面随后将以状态代码200提供.


Kyl*_*Mit 6

详细阐述Valin的评论,并内嵌Brock Allen的解决方案。

线索在于返回的OK响应,该响应在内部捕获到表单登录名的重定向:

X-Responded-JSON: {"status": 401, "headers": {"location":"http:\/\/localhost:50004\/Login?ReturnUrl=%2FClient"}}
Run Code Online (Sandbox Code Playgroud)

如果您想在服务器上进行修复,则可以使用Brock Allen的文章“ 将cookie身份验证中间件与Web API和401响应代码结合使用”中的解决方案,而不必为内部错误状态抓取响应

通常,当使用cookie身份验证中间件时,当服务器(MVC或WebForms)发出401消息时,响应将转换为302重定向到登录页面(由CookieAuthenticationOptions上的LoginPath配置)。但是,当进行Ajax调用且响应为401时,将302重定向返回到登录页面是没有意义的。相反,您只希望返回401响应。不幸的是,这不是我们通过cookie中间件获得的行为-响应被更改为200状态代码,并带有带有消息的JSON响应主体:

{"Message":"Authorization has been denied for this request."}
Run Code Online (Sandbox Code Playgroud)

我不确定此功能的要求是什么。要对其进行更改,必须通过在cookie身份验证中间件上配置CookieAuthenticationProvider来控制出现401未经授权的响应时的行为控制:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
   AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
   LoginPath = new PathString("/Account/Login"),
   Provider = new CookieAuthenticationProvider
   {
      OnApplyRedirect = ctx =>
      {
         if (!IsAjaxRequest(ctx.Request))
         {
            ctx.Response.Redirect(ctx.RedirectUri);
         }
     }
   }
});
Run Code Online (Sandbox Code Playgroud)

请注意,它处理OnApplyRedirect事件。当呼叫不是Ajax呼叫时,我们将重定向。否则,我们什么也不做,这不允许401返回给调用者。

只需从katana项目中的帮助程序复制对IsAjaxRequest的检查:

private static bool IsAjaxRequest(IOwinRequest request)
{
   IReadableStringCollection query = request.Query;
   if ((query != null) && (query["X-Requested-With"] == "XMLHttpRequest"))
   {
      return true;
   }
   IHeaderDictionary headers = request.Headers;
   return ((headers != null) && (headers["X-Requested-With"] == "XMLHttpRequest"));
}
Run Code Online (Sandbox Code Playgroud)