限制对OData$expand操作中数据的访问

本文关键字:数据 访问 操作 expand OData | 更新日期: 2024-10-23 21:15:38

我的数据库中有两个实体在ASP.NET WebApi 2 OData中公开:服务EmployeeActivity。为了简单起见,我们假设它们看起来是这样的:

public class Employee {
    public int Id { get; set; }
    public string Type { get; set; }
}
public class Activity {
    public int Id { get; set; }
    public int EmployeeId { get; set; }
    public virtual Employee OpenedBy { get; set; }
}

请注意,OpenedBy属性对应于导航属性,例如,我可以运行以下OData查询:

GET http://localhost/odata/Activities?$expand=OpenedBy

我想阻止某些Employee类型显示在OData中。假设我不能在数据源上执行此操作,所以我必须在代码中执行此操作。

到目前为止,我所做的是在EmployeesController(继承自EntitySetController)中阻止这些类型:

[Queryable]
public override IQueryable<Employee> Get() {
    return dbContext.Employees.Where(e => e.Type != "Restricted").AsQueryable();
}
[Queryable]
protected override Employee GetEntityByKey([FromODataUri] int key) {
    var employee = dbContext.Employees.Find(key);
    if (employee == null || employee.Type == "Restricted") {
        throw new ODataException("Forbidden");
    }
    return employee;
}

这很好用。然而,我注意到,如果我运行查询:

GET http://localhost/odata/Activities?$expand=OpenedBy

我没有命中Employees控制器中的代码,因此受限制的员工记录是可见的。防止这种情况发生的好方法是什么?

限制对OData$expand操作中数据的访问

在这种情况下:http://localhost/odata/Activities?$expand=由打开

我认为您应该更改ActivityController中的代码,$expand将在那里点击Get-Activity方法

如果不想一直展开OpenedBy,可以添加一个属性:[NotExpandable]

希望这能有所帮助:)

因为你说"我注意到如果我运行查询",我得到的印象是,这是一个副作用,你很乐意在任何情况下限制它。如果是这样的话,Mike Wasson的这篇文章可能对你有用。

在那篇文章中,他提出了两种限制odata访问属性的方法:

  1. 模型上的属性
  2. 以编程方式将其从EDM中删除

我没有尝试第一个,我不确定你需要使用哪个命名空间或库,但是,在这个问题的情况下,它看起来是这样的:

public class Activity {
    public int Id { get; set; }
    public int EmployeeId { get; set; }
    [IgnoreDataMember]
    public virtual Employee OpenedBy { get; set; }
}

我使用了第二种方法,对于问题中给出的例子,这看起来像这样:

var activities = modelBuilder.EntitySet<Activity>("Activities");
activities.EntityType.Ignore(a => a.OpenedBy);

我已经用这种方式限制了一些导航集合,它运行得很好。