使用HttpResponseMessage 401在ajaxpost上取得成功

我总是在客户端的ajaxpost上获得statusCode=200 ,而服务器使用HttpStatusCode.Unauthorized回答。

我的控制器代码:

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

我的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)); }); 

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

 { "Message": "Unauthorized login." } 

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

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

一旦您返回HttpStatusCode.Unauthorized ,您的页面可能会被表单身份validation模块重定向到登录页面。

来自MSDN:

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

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

由于返回的状态为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; } } 

详细阐述Valin的评论,以及内联Brock Allen的解决方案。

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

 X-Responded-JSON : {"status": 401, "headers": {"location":"http:\/\/localhost:50004\/Login?ReturnUrl=%2FClient"}} 

如果您想要修复服务器,而不是抓取此内部错误状态的响应,您可以使用Brock Allen关于使用带有Web API和401响应代码的cookie身份validation中间件的文章中的解决方案:

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

 {"Message":"Authorization has been denied for this request."} 

我不确定这项function的要求是什么。 要改变它,您必须通过在cookie身份validation中间件上配置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); } } } }); 

请注意它处理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")); }