从 webapi2 控制器返回 403

Returning a 403 from a webapi2 controller

我的API有以下路线

获取:api/departments

获取:api/departments/{departmentID}/employees

第二个路由映射到以下控制器操作

public IEnumerable<Employee> Get(int departmentID)
{
  return GetEmployees(departmentID);
}

可能会使用不存在或用户无权访问的 departmentID 调用此路由。遇到这种情况,正确的处理方式是什么?目前,我已将我的控制器操作修改为 return a 403,如下所示

public HttpResponseMessage Get(int departmentID)
{
  var isDepartmentValid = CheckIfDepartmentIsAccessible(username, departmentID);
  if(!isDepartmentValid)
  {
    return Request.CreateResponse(HttpStatusCode.Forbidden);
  }

   Request.CreateResponse(HttpStatusCode.OK, GetEmployees(departmentID));
}

这样做正确吗?似乎方法签名的更改使得从控制器操作中理解内容类型 return 变得更加困难。有没有办法让方法签名保持不变,但如果需要仍然 return 403?

对我来说,放置各种 authentication/authorization 的最佳位置是在 OWIN 中间件或某些 Authorize 操作过滤器中;但取决于您的要求,因为如果您没有更多需要身份验证的路由,我可能会按原样保留解决方案并在控制器操作本身内部进行检查。

您可以执行以下操作:

public IEnumerable<Employee> Get(int departmentID)
{
    var isDepartmentValid = CheckIfDepartmentIsAccessible(username, departmentID);
    if (!isDepartmentValid)
    {
        throw new HttpResponseException(HttpStatusCode.Forbidden);
    }

    return Request.CreateResponse(HttpStatusCode.OK, GetEmployees(departmentID));
}

要添加到 Rob Davis 的回答中,我建议您这样做,这样您就不需要更改方法的签名,并且 returned 响应对客户更有意义:

public IEnumerable<Employee> Get(int departmentID)
{
   try
   {
      return GetEmployees(departmentID);
   }
   catch(Exception ex) //assuming invalid dept or unauthorized throw Argument & Security Exceptions respectively
   {
        if(ex is SecurityException)
            throw new HttpResponseException(HttpStatusCode.Forbidden);
        else if(ex is ArgumentException)
            throw new HttpResponseException(HttpStatusCode.NotFound);
        else
             //handle or throw actual unhandled exception
    }
}

这假定您正在使用例外,但显然可以进行任何其他类型的检查以查看该部门是否存在或他们是否具有访问权限。然后 return 正确的反应。由于这是一个 WebAPI,因此性能损失可以忽略不计,因为最大的瓶颈很可能是网络本身。