2016-04-14 9 views
1

WebAPI/ODataプロジェクトを使用して、アプリケーションのデータレイヤを公開しています。アクセス制御用Odataコントローラの追加フィルタリング

の.NET Framework 4.6.1
System.Web.OData、バージョン= 5.9.0.0

我々は、様々なデータセット(外科医、患者など)のためのいくつかのODataのコントローラを持っています。私が患者を検索しようとしている場合は、以下のようなOData Queryを発行して、希望する基準に合致する患者のリストを取得します。

http://localhost/MyService/Patients?$filter=contains($it/Name,”Joe”) 

問題はすべての患者を見ることができないことがあるということです。 RESTfulなAPIは外部から公開されるため、URLの操作によってセキュリティ要件を満たすためにクライアントに依存することはできません。

特定の患者へのユーザーアクセスを許可するクレームを使用すると、個々のユーザーへのアクセスを保護することは可能ですが、一致するユーザーの一覧を検索することはまったく機能しません。

http://localhost/MyService/Patients(Id) 

私がこれを回避し、患者を所有するエンティティを介してアクセスしようとすると、同じタイプの問題が次のより高いレベルで発生します。言い換えれば、外科医が患者を所有している場合、どのように私がアクセスできる外科医のリストを取得するのですか?

アクセス制御を実施するためにODataによって構築されたクエリにいくつかの追加基準を挿入する方法はありますか?

答えて

1

これは、患者のODataコントローラ

public class PatientsController : BaseODataController<Patient> 
{ 
    public override IQueryable<Patient> Get() 
    { 
     return base.Get(); 
    } 
    ... 
} 

それは>患者のIQueryable <を返すためのGETメソッドである...

我々が追加するために必要な唯一のものアクセス制御フィルタリングは、追加の述語を追加します。たとえば、

public override IQueryable<Patient> Get() 
{ 
    var qry = base.Get(); 
    return qry.Where(itm => itm.Name.FirstName.Contains("R")); 
} 

コントローラインフラストラクチャがのIQueryable <T>を列挙するときには、作業ユニット全体を評価し、最終的なクエリを生成します。

私はデータベースに対してトレースを実行し、それを

http://localhost/MyService/Patients?$filter=Surgeries/any(d:d/PreOpDataComplete%20eq%20true). 

(PreOpDataCompleteフラグが真であるところ言い換えれば手術を見つける。)のような、より複雑なのODataクエリを与えると、私は次のクエリが実行されて表示されます。

exec sp_executesql N'SELECT 
        [Project1].[C1] AS [C1], 
        [Project1].[Id] AS [Id], 
        [Project1].[Name_FirstName] AS [Name_FirstName], 
        [Project1].[Name_LastName] AS [Name_LastName], 
        [Project1].[Gender] AS [Gender], 
        [Project1].[BirthDate] AS [BirthDate], 
        [Project1].[MedicalRecordId] AS [MedicalRecordId], 
        [Project1].[Surgeon_Id] AS [Surgeon_Id] 
        FROM (SELECT 
            [Extent1].[Id] AS [Id], 
            [Extent1].[Name_FirstName] AS [Name_FirstName], 
            [Extent1].[Name_LastName] AS [Name_LastName], 
            [Extent1].[Gender] AS [Gender], 
            [Extent1].[BirthDate] AS [BirthDate], 
            [Extent1].[MedicalRecordId] AS [MedicalRecordId], 
            [Extent1].[Surgeon_Id] AS [Surgeon_Id], 
            1 AS [C1] 
            FROM [dbo].[Patient] AS [Extent1] 
            WHERE [Extent1].[Name_FirstName] LIKE N''%R%'' 
       )  AS [Project1] 
        WHERE  EXISTS (SELECT 
            1 AS [C1] 
            FROM [dbo].[Surgery] AS [Extent2] 
            WHERE ([Project1].[Id] = [Extent2].[Patient_Id]) AND ([Extent2].[PreOpDataComplete] = @p__linq__0) 
       )',N'@p__linq__0 bit',@p__linq__0=1 

そして、私は外科医が自分の患者を所有し、単純なセキュリティモデルを仮定し、私は私が許されてる外科医IDのリストを持っている場合は、私が期待した結果

{ 
    "@odata.context":"http://localhost/MyService/$metadata#Patients", 
    "value":[{ 
     "Name":{ 
      "FirstName":"Ronn", 
      "LastName":"Black" 
     }, 
     "Gender":"M", 
     "BirthDate":"1917-02-02T00:00:00-08:00", 
     "MedicalRecordId":"MRN 0001", 
     "Id":"8bf6dcc4-3f00-4a40-980c-ceb13f8f5360" 
    }] 
} 

を取得請求でのアクセス。

public partial class Surgeon : IBaseEntity 
{ 
    [Key] 
    public Guid Id { get; set; } 
    public virtual ICollection<Patient> Patients { get; set; } 
    . . . 
} 

私は、以下の変更を行う場合は今、私は私が見ることが許されてるだけの患者に任意の検索を制限することができます:

public override IQueryable<Patient> Get() 
{ 
    //IQueriable from the OData Selection 
    var qry = base.Get(); 
  
    //Enforce Access Security 
    var accessList = {get list of authorized surgeon id's from claims}; 
    var finalQry = uow.Surgeons 
        .Where(s => accessList.Contains(s.Id))  //Restrict to Surgeons I'm allowed to see 
        .SelectMany(surgeon => surgeon.Patients)  //All the patients I'm allowed to see (Left) 
        .Join(qry,                              //Join to Query (Right) 
            allowedPatients => allowedPatients.Id, //Key for Left 
            qryPatients => qryPatients.Id,         //Key for Right 
            (allowedPatients, qryPatients) =>      //Iterate through Matches 
            qryPatients);                          //Return the Matches from Right 
  
    return finalQry; 
} 

私はこのようになります外科医のエンティティを持っているでしょう
関連する問題