次の方法で共有


保護レベルについて

ProtectionLevel プロパティは、ServiceContractAttributeクラスやOperationContractAttribute クラスなど、さまざまなクラスで見つかります。 このプロパティは、メッセージの一部 (または全体) の保護方法を制御します。 このトピックでは、Windows Communication Foundation (WCF) 機能とそのしくみについて説明します。

保護レベルを設定する手順については、「 方法: ProtectionLevel プロパティを設定する」を参照してください。

保護レベルは、構成ではなく、コードでのみ設定できます。

基本情報

保護レベルの機能を理解するために、次の基本的なステートメントが適用されます。

  • メッセージの任意の部分に対して、3 つの基本的な保護レベルが存在します。 プロパティ (発生する場所) は、 ProtectionLevel 列挙値のいずれかに設定されます。 保護の昇順には、次のものが含まれます。

    • None

    • Sign。 保護された部分はデジタル署名されます。 これにより、保護されたメッセージ部分の改ざんが確実に検出されます。

    • EncryptAndSign。 メッセージ部分は、署名される前に機密性を確保するために暗号化されます。

  • この機能を使用して 、アプリケーション データ に対してのみ保護要件を設定できます。 たとえば、WS-Addressing ヘッダーはインフラストラクチャ データであるため、 ProtectionLevelの影響を受けません。

  • セキュリティ モードを Transport に設定すると、メッセージ全体がトランスポート メカニズムによって保護されます。 したがって、メッセージのさまざまな部分に対して個別の保護レベルを設定しても効果はありません。

  • ProtectionLevelは、開発者がバインディングが準拠する必要がある最小レベルを設定する方法です。 サービスがデプロイされると、構成で指定された実際のバインドが最小レベルをサポートする場合とサポートされない場合があります。 たとえば、既定では、 BasicHttpBinding クラスはセキュリティを提供しません (有効にすることはできますが)。 そのため、None 以外に設定したコントラクトとこのバインドを使用すると、例外がスローされます。

  • サービスで、すべてのメッセージの最小 ProtectionLevelSign必要な場合、クライアント (WCF 以外のテクノロジによって作成される場合もあります) は、すべてのメッセージを暗号化して署名できます (これは最低限必要な数を超えています)。 この場合、クライアントが最小値を超える処理を行っているため、WCF は例外をスローしません。 ただし、WCF アプリケーション (サービスまたはクライアント) は、可能であればメッセージ部分を過剰にセキュリティで保護しませんが、最小レベルに準拠します。 また、セキュリティ モードとして Transport を使用する場合、トランスポートは、本質的により細かいレベルでセキュリティで保護できないため、メッセージ ストリームを過剰にセキュリティで保護する可能性があることに注意してください。

  • ProtectionLevelを明示的に Sign または EncryptAndSign に設定した場合は、セキュリティが有効になっているバインドを使用する必要があります。そうしないと、例外がスローされます。

  • セキュリティを有効にするバインドを選択し、コントラクト上のどこにも ProtectionLevel プロパティを設定しない場合、すべてのアプリケーション データが暗号化され、署名されます。

  • セキュリティが有効になっていないバインド (たとえば、 BasicHttpBinding クラスのセキュリティが既定で無効になっている) を選択し、 ProtectionLevel が明示的に設定されていない場合、アプリケーション データは保護されません。

  • トランスポート レベルでセキュリティを適用するバインディングを使用している場合、すべてのアプリケーション データはトランスポートの機能に従ってセキュリティで保護されます。

  • メッセージ レベルでセキュリティを適用するバインディングを使用する場合、アプリケーション データはコントラクトに設定されている保護レベルに従ってセキュリティで保護されます。 保護レベルを指定しない場合、メッセージ内のすべてのアプリケーション データが暗号化され、署名されます。

  • ProtectionLevelは、さまざまなスコープ レベルで設定できます。 スコープには階層が関連付けられています。これについては、次のセクションで説明します。

スコープ設定

最上位の API で ProtectionLevel を設定すると、その下にあるすべてのレベルのレベルが設定されます。 ProtectionLevelが下位レベルで別の値に設定されている場合、階層内のそのレベルより下のすべての API は新しいレベルにリセットされます (ただし、その上の API は最上位レベルの影響を受けます)。 階層は次のとおりです。 同じレベルの属性は同等です。

プログラミング保護レベル

階層内の任意の時点で ProtectionLevel をプログラムするには、属性を適用するときにプロパティを適切な値に設定するだけです。 例については、「 方法: ProtectionLevel プロパティを設定する」を参照してください。

エラーとメッセージ コントラクトにプロパティを設定するには、それらの機能のしくみを理解する必要があります。 詳細については、「 方法: ProtectionLevel プロパティを設定 し、 メッセージ コントラクトを使用する」を参照してください。

WS-Addressing の依存関係

ほとんどの場合、 ServiceModel メタデータ ユーティリティ ツール (Svcutil.exe) を使用してクライアントを生成すると、クライアントコントラクトとサービス コントラクトが同じになります。 ただし、同じように見えるコントラクトによって、クライアントから例外がスローされる場合があります。 これは、バインディングが WS-Addressing 仕様をサポートせず、コントラクトで複数のレベルの保護が指定されるたびに発生します。 たとえば、 BasicHttpBinding クラスは仕様をサポートしていません。また、WS-Addressing をサポートしないカスタム バインドを作成する場合などです。 ProtectionLevel機能は、1 つのコントラクトで異なる保護レベルを有効にするために、WS-Addressing 仕様に依存しています。 バインドが WS-Addressing 仕様をサポートしていない場合、すべてのレベルが同じ保護レベルに設定されます。 コントラクト上のすべてのスコープの有効な保護レベルは、コントラクトで使用される最も強力な保護レベルに設定されます。

これにより、一見するとデバッグが困難な問題が発生する可能性があります。 複数のサービスのメソッドを含むクライアント コントラクト (インターフェイス) を作成できます。 つまり、同じインターフェイスを使用して多くのサービスと通信するクライアントを作成し、1 つのインターフェイスにすべてのサービスのメソッドを含めます。 開発者は、このまれなシナリオでは、特定のサービスごとに適用可能なメソッドのみを呼び出すように注意する必要があります。 バインドが BasicHttpBinding クラスの場合、複数の保護レベルをサポートすることはできません。 ただし、クライアントに応答するサービスは、必要な保護レベルよりも低い保護レベルでクライアントに応答する場合があります。 クライアントは期待される保護レベルがより高いため、この場合例外を発生させます。

コードの例は、この問題を示しています。 次の例は、サービスとクライアント コントラクトを示しています。 バインディングが <basicHttpBinding> 要素であるとします。 そのため、コントラクトに対するすべての操作の保護レベルは同じです。 この均一な保護レベルは、すべての操作の最大保護レベルとして決定されます。

サービス コントラクトは次のとおりです。

[ServiceContract()]
public interface IPurchaseOrder
{
    [OperationContract(ProtectionLevel = ProtectionLevel.Sign)]
    int Price();
}
<ServiceContract()> _
Public Interface IPurchaseOrder
    <OperationContract(ProtectionLevel:=ProtectionLevel.Sign)> _
    Function Price() As Integer
End Interface

次のコードは、クライアント コントラクト インターフェイスを示しています。 これには、別のサービスで使用することを意図した Tax メソッドが含まれていることに注意してください。

[ServiceContract()]
public interface IPurchaseOrder
{
    [OperationContract()]
    int Tax();

    [OperationContract(ProtectionLevel = ProtectionLevel.Sign)]
    int Price();
}
<ServiceContract()> _
Public Interface IPurchaseOrder
    <OperationContract()> _
    Function Tax() As Integer

    <OperationContract(ProtectionLevel:=ProtectionLevel.Sign)> _
    Function Price() As Integer
End Interface

クライアントは、 Price メソッドを呼び出すと、サービスから応答を受け取ったときに例外をスローします。 これは、クライアントがProtectionLevelServiceContractAttributeを指定していないため、クライアントが EncryptAndSign メソッドを含むすべてのメソッドに対して既定の (Price) を使用するためです。 ただし、サービス コントラクトでは保護レベルが Sign に設定されている 1 つのメソッドが定義されているため、サービスはSign レベルを使用して値を返します。 この場合、クライアントはサービスからの応答を検証するときにエラーをスローします。

こちらも参照ください