c# - 如何保护 Web API 免受数据检索而不是来自资源所有者的数据检索

标签 c# asp.net-web-api asp.net-web-api2 service-layer

我有一个 asp.net web api。

我想稍后在一个 Azure 网站上自行托管我的 Web API。

登录用户可以在浏览器中执行此操作 /api/bankaccounts/3

获取有关银行帐号 3 的所有详细信息

但登录用户不是银行帐号3的所有者。

我必须如何设计我的 Controller 及其背后的服务

在数据库中用户只能检索/修改自己的资源吗?

更新

在我创建一个之后:

public class UserActionsAuthorizationFilter : AuthorizationFilterAttribute
{
   public override void OnAuthorization(HttpActionContext actionContext)
   {
       if (actionContext != null)
       { 
           bool canUserExecuteAction = IsResourceOwner(actionContext);
           // stop propagation  
       }
   }

private bool IsResourceOwner(HttpActionContext actionContext)
        {
            var principal = (ClaimsPrincipal)Thread.CurrentPrincipal; 
            var userIdAuthenticated = Convert.ToInt32(principal.Claims.Single(c => c.Type == ClaimTypes.Sid).Value);

            int targetId = Convert.ToInt32(actionContext.Request.GetRouteData().Values["Id"]);
            var requstScope = actionContext.ControllerContext.Request.GetDependencyScope();
            var service = (ISchoolyearService)requstScope.GetService(typeof(ISchoolyearService));
            bool canUserExecuteAction = service.HasUserPermission(userIdAuthenticated, targetId);
            return canUserExecuteAction;
        }
}

现在的问题是 IsResouceOwner 被硬编码到某个服务 => SchoolyearService 因此绑定(bind)到 Schoolyear SQL 表

我需要让 IsResourceOwner 方法对所有具有字段 UserId/UserEmail 的 sql 表保持通用。

问题是 - 我真的认为没有人这样做 - 我必须在 HasUserPermission 方法中将每个资源所有者检查映射到正确的 Sql 表。

映射应该是什么样子的?

检查 Controller 名称“SchoolyearController”因此要检查的表是“schoolyear”表?太荒谬了。

这个自定义属性“UserActionsAuthorizationFilter”将出现在每个“数据” Controller 上。

无论用户触发什么 Controller url 来获取数据,在我必须检查他是否是资源所有者之前。

我想我无法在过滤器中决定这一点。

我必须让数据检索/修改通过 Controller ,并在数据检索完成之前在存储库中进行 ResourceOwner 检查。

你怎么看这个:

API

public async Task<IHttpActionResult> Delete(int id)
{
   var result = await service.Delete(id, User.Identity.UserId);
    if (result == 0)
        return NotFound();
    return Ok();
}

repo

    public async Task<int> Delete(int id, int userId)
    {
        var schoolyerToDelete = await context.Schoolyears.SingleOrDefaultAsync(s => s.Id == id && s.UserId == userId); 

// If schoolyearToDelete is null nothing is removed, thus the affected rows are ZERO.
        context.Schoolyears.Remove(schoolyerToDelete);
       return await context.SaveChangesAsync();
    }
  • 对于错误的 UserId,Get 方法不会返回任何内容
  • 对于 Create 方法:没问题,如果登录,每个人都应该能够创建资源。
  • 对于 Update 方法:与 Delete 方法相同,学年由 id 和 UserId 检索。

一般来说,我存储库中的每个方法都应该考虑 CRUD 操作中的 UserId。

你怎么看?

最佳答案

这是一个老问题,但对于遇到类似问题的任何人,这里有一个可能的解决方案。

添加一个抽象层

  • 您可以像以前一样使用 UserActionsAuthorizationFilter 来凑合;只需执行以下操作
  • 让你所有的服务接口(interface)(比如 ISchoolyearService)继承一个定义了 HasUserPermission 的通用接口(interface)
public interface IService {
  HasUserPermission(int32 userIdAuthenticated, int targetId));}

public interface ISchoolyearService : IService {
  /* Include all other methods except for HasUserPermission */
}
  • 在 UserActionsAuthorizationFilter 中,添加一个字段:“internal IService ServiceProvider”
  • 在 UserActionsAuthorizationFilter 中,修改 IsResourceOwner():

来自

var service = (ISchoolyearService)requstScope.GetService(typeof(ISchoolyearService));

var service = (IService)requstScope.GetService(this.ServiceProvider);
- Then, change all the attributes on your Controllers to specify which type of IService they use
[UserActionsAuthorizationFilter(ServiceProvider = typeof(ISchoolyearService))] <br> internal SchoolyearController : Controller { }

这种方法的显着缺点是您随后 promise 仅允许用户访问通过 HasUserPermission() 检查的用户,因此您无法进行任何操作应该可以公开访问的更深层次的 URL,例如 /api/testresults/3/public

P.S> 你是对的,根据 Controller 名称找出要检查哪个 SQL 表是荒谬的😊

关于c# - 如何保护 Web API 免受数据检索而不是来自资源所有者的数据检索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30817347/

相关文章:

c# - 如何使用 OData 在 Dictionary<string, string> 上进行 $filter?

c# - 'Emgu.CV.CvInvoke' 的类型初始值设定项抛出异常

c# - 数据表选择 : Expression with a space problem

c# - OWIN/武士刀 & BasicAuthentication

c# - 在命令行上告诉 OwinHost 如何在项目外部使用 cwd 加载 OwinSetup 类

c# - 如何从 WEB API 请求和响应 XML 中删除命名空间?

c# - 将 XML 读入数组,不断出现错误

c# - 延迟任务开始的正确方法

c# - MVC 4 Web Api 发布

javascript - 在按钮上调用操作方法单击 ASP.NET MVC