2

Service クラスを実装しました。「DataSourceService」としましょう。今、私はそれを WCF を介して公開し、REST にしたいと考えています。問題はありません。これは WCF で簡単に実行できます。

しかし、ここでアーキテクチャの問題が発生します。

だから私はメソッドを持っているとしましょう:

 IEnumerable<string> ReadAllInventoryItems()

IEnumerable<string>ユーザー認証クレーム (役割や権限など) に応じて返さなければならない問題。これは、DataSourceService の各メソッドでこれらのクレームを検証することで実現できます。そんな感じ:

IEnumerable<string> ReadAllInventoryItems()
{
     var companyName = ReadCompanyNameFromAuthorisationContext();
     var items = ReadAll().Where( i => i.CompanyName == companyName).ToList();
     return Items;
}

このアプローチには大きな問題が 1 つあります。つまり、DataSourceService は、この "Claims" コンテキストがないと使用できなくなります。WCF なしで使用する場合は、呼び出しごとに Claims または UserIdentity コンテキストを準備する必要があります。

したがって、次のステップは「WCF IDispatchMessageInspector について考える」ことでしたが、1 つの IDispatchMessageInspector と 1 つの OperationInvoker を実装する必要があることに気付きました。その後、アクセス許可を持つ何らかの属性で Web サービス メソッドを装飾できます (この属性は、後で OperationInvoker で使用されます)。 )。

最後に私は得るでしょう:

    [AuthorizationFiltering]
    IEnumerable<string> ReadAllInventoryItems()
    {         
         var items = ReadAll().Where( i => i.CompanyName == companyName).ToList();
         return Items;
    }

あれについてどう思う?

「DataSourceServiceの各メソッドでこれらのクレームを検証する」またはWCF IDispatchMessageInspectorに固執する必要がありますか、MethodInvokerの話はそれほど悪くありません...

4

2 に答える 2

0

APIをどのように設計するかによって異なりますが、APIを公開して直感的に使用できるようにする場合は、承認コンテキスト内の「フィルター」を(クレームのように)不明瞭にすることはお勧めできません。発信者、私があなたのサービスに電話しなければならない場合、私はあなたがあなたの発信者にどのような主張を期待しているのかを正確に知る必要があります。

ただし、すべての発信者がクレームベースの承認を使用していることを知っている場合は、特定のクレームを「要求」するようにメソッドを設計できます。そうすれば、アプローチは問題ありません。そして、たとえば次のようなものを使用できます。

[PrincipalPermission(SecurityAction.Demand, Role = ManagersWithInventory)]

ただし、呼び出し元がこの特定のクレームを持っていない場合、呼び出し元はメソッドを呼び出すことができないことに注意してください。つまり、それが望ましい動作であるかどうかはわかりません。

非常に単純なケースでは、次のような明示的な「フィルター」を使用してサービス呼び出しを設計します。

MyService.GetInventoryByReferenceId(string Id)

このコントラクトにより、呼び出しは非常に直感的になり、フィルターの設定方法を決定するのは呼び出し元の責任です。

編集

わかりました。IDispatchMessageInspectorの実装が間違っていると言っているわけではありませんが、データを不必要に「スニッフィング」しているにもかかわらず、発信者のIDを取得するために別の外部ラウンドトリップを行う必要があるため、おそらくやややり過ぎです。

はるかに優れたアプローチは、「実際の」クレームID:Microsoft.IdentityModel.dllを両側で使用し、クレームを透過的に処理して、WCFにクレデンシャルを転送させることだと思います。

WIFは以前のIIdentityをIClaimsIdentityでラップするため、サービスを呼び出す古いデスクトップアプリケーションは引き続き機能し、クレームの有無にかかわらず「ユーザー」と連携することもできます(サービス側で)。

それが役に立てば幸い、

于 2012-11-20T12:28:11.890 に答える
0

更新/解決策?:

いくつかの考えとホルヘ・アルバラードのコメントの後。私は次のことを実装することにしました。

つまり... Service クラスはセキュリティ コンテキストを認識していません。プロパティ(列挙)「CompanyName」があることでわかっていること。例えば:

public ClientEnumerationType? CurrentClient { get; set; }

ReadInventory 関数から結果を返したい場合、次のコードがあります。

IEnumerable<string> ReadAllInventoryItems()
{
     var items = ReadAll();

     return CurrentClient.HasValue ? FilterByClient(items, urrentClient.Value).ToList() : items;
}

したがって、その実装により、WCF の外部でそのクラスを問題なく使用できます。

WCFはどうですか?私は WCF から正確に何が必要かを考えていましたが、実際に必要なものは 1 つだけです。クライアントを承認し、サービス クラスをインスタンス化し、CurrentClient プロパティの値を設定します。

それを可能にするために、私はいくつかのことを実装しました。

1) IEndpointBehavior

コントラクト メソッドごとに Message Inspector と InstanceProvider および ParameterInspectors をインストールするために必要です。

2) IDispatchMessageInspector

WCF メッセージを受け取り、要求からトークンを抽出し、トークンを検証して、Thread.CurrentPrincipal を要求からのすべてのクレーム値を使用して ClaimsPrincipal に設定します。

3)IParameterInspector

コントラクトのメソッドごとに Claim = Action を検証するために必要です。たとえば、私は持っています:

    [OperationContract]
    [ClaimActionRequred(Action = "read")]        
    IEnumerable<string> ReadAllInventoryItems()

つまり、ID プロバイダーはクライアント トークンのアクション クレームを提供する必要があります。そして、そのクレーム値は、実際の呼び出しが行われる前に、IParameterInspector で分析されています。

4) 最後のピース - IInstanceProvider

必要なのは、ServiceClass をインスタンス化し、Claim Value に応じて CurrentClient プロパティ値を渡すことだけです。

終わり。

私はそれを正しく行ったかどうか確信が持てません。しかし、これは私が作った解決策です。

于 2012-11-21T16:05:02.203 に答える