7

安全なWCFサービスを実装しています。認証は、ユーザー名/パスワードまたはWindowsクレデンシャルを使用して行われます。このサービスは、Windowsサービスプロセスでホストされます。今、私は各サービス操作の承認を実装するための最良の方法を見つけようとしています。

たとえば、次の方法について考えてみます。

public EntityInfo GetEntityInfo(string entityId);

ご存知かもしれませんが、WCFには、呼び出し元/クライアントから渡されたセキュリティ資格情報を取得できるOperationContextオブジェクトがあります。これで、メソッドの最初の行が呼び出されるまでに、認証はすでに終了しているはずです。しかし、決定が入力データ自体に依存する場合、どのように承認を実装しますか?たとえば、上記の場合、「admin」ユーザー(権限などがデータベースに保存されている)はエンティティ情報の取得を許可され、他のユーザーは許可されるべきではありません...承認チェックはどこに配置しますか?

次のように、メソッドの最初の行に配置するとします。

CheckAccessPermission(PermissionType.GetEntity, user, entityId) //user is pulled from the current OperationContext

ここで、いくつかの質問があります。

  1. 承認チェックの前または承認チェックの内部でentityIdを検証しますか(たとえば、null /空の値をチェックしますか?)言い換えれば、承認チェックをすべてのメソッドに含める必要がある場合、それは良いパターンですか?どちらを最初に行う必要がありますか-引数の検証または承認?

  2. 承認チェックがこのように至る所にあり、単体テストにOperationContextがない場合、WCFサービスを単体テストするにはどうすればよいですか?(WCFを設定せずに、このサービスクラスの実装を直接テストしようとしていると仮定します)。

アイデアはありますか?

4

3 に答える 3

6

質問 2 については、依存性注入を使用してこれを行い、サービスの実装を次のように設定します。

class MyService : IMyService
{
    public MyService() : this(new UserAuthorization()) { }
    public MyService(IAuthorization auth) { _auth = auth; }

    private IAuthorization _auth;

    public EntityInfo GetEntityInfo(string entityId)
    {
            _auth.CheckAccessPermission(PermissionType.GetEntity, 
                    user, entityId);

            //Get the entity info
    }
}

IAuthorization は、ユーザーが定義するインターフェイスであることに注意してください。

サービスの種類を直接 (つまり、WCF ホスティング フレームワーク内で実行せずに) テストするので、すべての呼び出しを許可するダミーの IAuthorization 型を使用するようにサービスを設定するだけです。ただし、さらに優れたテストは、IAuthorization をモックし、期待するパラメーターを使用していつ呼び出されるかをテストすることです。これにより、メソッド自体とともに、認証メソッドへの呼び出しが有効であることをテストできます。

承認を独自のタイプに分離することで、それが正しいことを分離して簡単にテストすることもできます。私の(限定的ではありますが)経験では、DI「パターン」を使用すると、懸念事項の分離とタイプのテスト可能性が大幅に向上し、よりクリーンなインターフェースが得られます(これは明らかに議論の余地があります)。

私のお気に入りのモッキング フレームワークはRhinoMocks です。これは無料で流暢なインターフェイスを備えていますが、他にもたくさんあります。DI について詳しく知りたい場合は、いくつかの優れた入門書と .Net フレームワークを以下に示します。

于 2009-03-17T14:45:12.090 に答える
6

質問 1 については、最初に承認を実行することをお勧めします。そうすれば、検証エラー メッセージが権限のないユーザーに漏れることはありません。

ところで、自家製の認証方法を使用する代わりに (これは CheckAccessPermission と同じだと思います)、ASP.NET ロール プロバイダーに対する WCF のすぐに使えるサポートに接続できる場合があります。これが完了したら、OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.IsInRole() を介して承認を実行します。PrimaryIdentity は IPrincipal です。

于 2008-09-28T03:42:39.880 に答える
3

質問1については、絶対に最初に承認を行ってください。最も厳格なセキュリティを維持するために、承認前に(制御内の)コードを実行しないでください。上記のポールの例は素晴らしいです。

質問2の場合、具体的なサービス実装をサブクラス化することでこれを処理できます。上記のように、真のビジネスロジック実装を抽象「CheckPermissions」メソッドを使用して抽象クラスにします。次に、2つのサブクラスを作成します。1つはWCF用で、もう1つはtrue(または単体テストで実行したいこと)を返すサブクラスです(デプロイされていないDLLで非常に分離されています)。

例(ただし、これらは同じファイルまたはDLLに含めるべきではないことに注意してください!):

public abstract class MyServiceImpl
{
    public void MyMethod(string entityId)
    {
        CheckPermissions(entityId);
        //move along...
    }
    protected abstract bool CheckPermissions(string entityId);
}

public class MyServiceUnitTest
{
    private bool CheckPermissions(string entityId)
    {
        return true;
    }
}

public class MyServiceMyAuth
{
    private bool CheckPermissions(string entityId)
    {
        //do some custom authentication
        return true;
    }
}

次に、WCFデプロイメントでクラス「MyServiceMyAuth」を使用し、他のクラスに対して単体テストを実行します。

于 2008-09-28T20:06:03.107 に答える