C# ASP.NETWebAPI和jQueryAjax-如何处理未经授权的结果

C# ASP.NETWebAPI和jQueryAjax-如何处理未经授权的结果,c#,jquery,asp.net,ajax,asp.net-web-api2,C#,Jquery,Asp.net,Ajax,Asp.net Web Api2,我使用以下asp.net web api方法删除文件: [Authorize] [HttpPost] public IHttpActionResult Delete(int id) { var uploadedFile = unitOfWork.FileRepository.Get(id); if (uploadedFile == null) return NotFound(); if

我使用以下asp.net web api方法删除文件:

    [Authorize]
    [HttpPost]
    public IHttpActionResult Delete(int id)
    {

        var uploadedFile = unitOfWork.FileRepository.Get(id);

        if (uploadedFile == null)
            return NotFound();

        if (uploadedFile.CreatedBy != User.Identity.GetUserId())
            return Unauthorized();

        unitOfWork.FileRepository.Remove(uploadedFile);

        unitOfWork.Complete();

        return Ok();
    } 
如果试图删除文件的用户没有创建文件,我想返回一个
未经授权的
结果。我有下面的ajax来处理调用,但是在测试时,我总是得到响应200,因此在我的ajax函数中从未调用fail函数

我已经调试了带有断点的web api方法,它显然触发了未经授权的方法-
return Unauthorized()

那么,当我在firefox控制台中查看时,为什么会返回状态200:

POST http://localhost:65179/api/file/2 200 OK 29ms
当我在控制台中检查响应标头时,它显示以下内容:

 X-Responded-JSON {"status":401,"headers":{"location":"http:\/\/localhost:65179\/Account\/Login?ReturnUrl=%2Fapi%2Ffile%2F94"}}
所以我不知道为什么不调用fail函数?我认为它正在重定向到登录页面,因此状态返回为200。那么,如何抑制重定向

 function () {
        $.ajax({
            url: "api/file/2",
            method: "POST"
        })
        .done(function () {

            alert("File has been deleted.");
        })
        .fail(function ( jqXHR) {
            alert("Unable to delete file");

        });
   });
***更新****

我发现下面的博文是一个潜在的解决方案,但只有当您的项目只是WebAPI时,它才会起作用

我的项目是MVC 5和web api 2的组合,因此我对其进行了修改,并将代码添加到startup.auth.cs中,如下所示,但我必须注释掉
OnValidateIdentity
位,以便将
OnApplyRedirect
添加到cookieoptions中

public void ConfigureAuth(IAppBuilder app)
    {
        var cookieOptions = new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            {
                // Enables the application to validate the security stamp when the user logs in.
                // This is a security feature which is used when you change a password or add an external login to your account.  
                //OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                //    validateInterval: TimeSpan.FromMinutes(30),
                //    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))

                OnApplyRedirect = ctx =>
                {
                   if (!IsApiRequest(ctx.Request))
                   {
                       ctx.Response.Redirect(ctx.RedirectUri);
                    }
                 }
            }
        };

        app.UseCookieAuthentication(cookieOptions);

    }

    private static bool IsApiRequest(IOwinRequest request)
    {
       string apiPath = VirtualPathUtility.ToAbsolute("~/api/");
       return request.Uri.LocalPath.StartsWith(apiPath);
    }
public void ConfigureAuth(IAppBuilder应用程序)
{
var cookieOptions=新的CookieAuthenticationOptions
{
AuthenticationType=DefaultAuthenticationTypes.ApplicationOkie,
LoginPath=新路径字符串(“/Account/Login”),
Provider=新CookieAuthenticationProvider
{
//允许应用程序在用户登录时验证安全戳。
//这是一种安全功能,在您更改密码或向帐户添加外部登录时使用。
//OnValidateIdentity=SecurityStampValidator.OnValidateIdentity(
//validateInterval:TimeSpan.FromMinutes(30),
//regenerateIdentity:(管理器,用户)=>user.GenerateUserIdentityAsync(管理器))
OnApplyRedirect=ctx=>
{
如果(!IsApiRequest(ctx.Request))
{
响应重定向(ctx.RedirectUri);
}
}
}
};
应用程序UseCookieAuthentication(cookieOptions);
}
私有静态bool IsApiRequest(IOwinRequest请求)
{
字符串apiPath=VirtualPathUtility.ToAbsolute(“~/api/”);
return request.Uri.LocalPath.StartsWith(apiPath);
}

正确的方法是使用错误回调

$.ajax({
            url: "api/file/2",
            method: "POST"
        })
        .success(function () {

            alert("File has been deleted.");
        })
        .error(function (xhr, textStatus, errorThrown) {
            alert("Unable to delete file");

        });

参见文档

您可以从作为
.fail(function(jqXHR){})
的第一个参数提供的对象中提取信息。对象具有返回数字状态代码的属性。返回的状态代码是标准的


在这种情况下返回的状态码不应该是
禁止的(403)
而不是
未经授权的(401)
,这更有意义-
返回新的HttpResponseMessage(HttpStatusCode.Forbidden)

状态代码401(未授权)和403(禁止)具有不同的 意义

401响应表示对资源的访问受到限制, 请求没有提供任何HTTP身份验证。它是 对相同资源的新请求可能会成功,如果 提供身份验证。响应必须包括HTTP WWW Authenticate标头以提示用户代理提供 资格证书如果未通过HTTP提供有效凭据 授权,则不应使用401。[2]

403响应通常表示以下两种情况之一:

  • 已提供身份验证,但未提供经过身份验证的用户 允许执行请求的操作
  • 手术正在进行中 禁止所有用户使用。例如,请求目录列表 禁用目录列表时返回代码403

.fail()
的第一个参数是一个jqXHR,它具有状态属性。在这种情况下,返回的状态代码不应该是
禁止的(403)
,而不是
未经授权的(401)
,后者更有意义-
返回新的HttpResponseMessage(HttpStatusCode.Forbidden)
。-虽然..@Developer很好,但不确定中间件是否也能处理403。如果你将你的评论添加为解决方案,我会将其标记为解决方案,请参阅更新的帖子。我注意到调用
returnunauthorized()
始终返回状态200,因此不会调用fail函数?@adam78,如果它返回
200
,则它不是
未经授权的
,您可以测试
。always()
,正如名称所示,它将始终执行我的更新帖子。web方法肯定会返回Unauthorized,因为当我重新加载页面时,文件仍然存在。如果我尝试与创建该文件的用户进行相同操作,则该文件将按预期工作,即删除该文件。
$.ajax({
    url: "api/file/2",
    method: "POST"
})
.fail(function (jXHR) {
    if (jXHR.status == 401) {
        alert('Unauthorised')
    }   
});