如何:设置 ProtectionLevel 属性

通过应用相应的属性 (Attribute) 并设置该属性 (Property) 可设置保护级别。 可在服务级设置保护以影响每条消息的所有部分,或者可以从方法到消息部分逐级递增地设置保护。 如需详细了解 ProtectionLevel 属性,请参阅了解保护级别

注意

只能在代码中,而不是在配置中设置保护级别。

为服务签名所有消息

  1. 为服务创建一个接口。

  2. ServiceContractAttribute 属性 (Attribute) 应用于服务,并将 ProtectionLevel 属性 (Property) 设置为 Sign,如下面的代码所示(默认级别为 EncryptAndSign)。

    // Set the ProtectionLevel on the whole service to Sign.
    [ServiceContract(ProtectionLevel = ProtectionLevel.Sign)]
    public interface ICalculator
    
    ' Set the ProtectionLevel on the whole service to Sign.
    <ServiceContract(ProtectionLevel:=ProtectionLevel.Sign)> _
    Public Interface ICalculator
    

为操作签名所有消息部分

  1. 为服务创建一个接口,并将 ServiceContractAttribute 属性应用于该接口。

  2. 向该接口添加一个方法声明。

  3. OperationContractAttribute 属性 (Attribute) 应用于该方法,并将 ProtectionLevel 属性 (Property) 设置为 Sign,如下面的代码所示。

    // Set the ProtectionLevel on the whole service to Sign.
    [ServiceContract(ProtectionLevel = ProtectionLevel.Sign)]
    public interface ICalculator
    {
        // Set the ProtectionLevel on this operation to None.
        [OperationContract(ProtectionLevel = ProtectionLevel.Sign)]
        double Add(double a, double b);
    }
    
    ' Set the ProtectionLevel on the whole service to Sign.
    <ServiceContract(ProtectionLevel:=ProtectionLevel.Sign)> _
    Public Interface ICalculator
    
        ' Set the ProtectionLevel on this operation to Sign.
        <OperationContract(ProtectionLevel:=ProtectionLevel.Sign)> _
        Function Add(ByVal a As Double, ByVal b As Double) As Double
    End Interface
    

保护错误消息

服务上引发的异常可以作为 SOAP 故障发送到客户端。 有关创建强类型错误的详细信息,请参阅在协定和服务中指定和处理错误如何在服务协定中声明错误

保护错误消息

  1. 创建一个表示错误消息的类型。 下面的示例创建一个含有两个字段的名为 MathFault 的类。

  2. DataContractAttribute 属性应用于该类型,并将 DataMemberAttribute 属性应用于应该序列化的每个字段,如下面的代码所示。

    [DataContract]
    public class MathFault
    {
        [DataMember]
        public string operation;
        [DataMember]
        public string description;
    }
    
    <DataContract()> _
    Public Class MathFault
        <DataMember()> _
        Public operation As String
        <DataMember()> _
        Public description As String
    End Class
    
  3. 在将返回该错误的接口中,将 FaultContractAttribute 属性应用于将返回错误的方法,并将 detailType 参数设置为错误类的类型。

  4. 同样在构造函数中,将 ProtectionLevel 属性设置为 EncryptAndSign,如下面的代码所示。

    public interface ICalculator
    {
        // Set the ProtectionLevel on a FaultContractAttribute.
        [OperationContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
        [FaultContract(
            typeof(MathFault),
            Action = @"http://localhost/Add",
            Name = "AddFault",
            Namespace = "http://contoso.com",
            ProtectionLevel = ProtectionLevel.EncryptAndSign)]
        double Add(double a, double b);
    }
    
    Public Interface ICalculator
        ' Set the ProtectionLevel on a FaultContractAttribute.
        <OperationContract(ProtectionLevel:=ProtectionLevel.EncryptAndSign), _
         FaultContract(GetType(MathFault), ProtectionLevel:=ProtectionLevel.EncryptAndSign)> _
        Function Add(ByVal a As Double, ByVal b As Double) As Double
    End Interface
    

保护消息部分

使用消息协定来保护消息的各个部分。 有关消息约定的详细信息,请参阅使用消息约定

保护消息正文

  1. 创建一个表示消息的类型。 下面的示例创建一个 Company 类,其中有两个字段 CompanyNameCompanyID

  2. MessageContractAttribute 属性 (Attribute) 应用于该类,并将 ProtectionLevel 属性 (Property) 设置为 EncryptAndSign

  3. MessageHeaderAttribute 属性 (Attribute) 应用于将表示为消息头的字段,并将 ProtectionLevel 属性 (Property) 设置为 EncryptAndSign

  4. MessageBodyMemberAttribute 应用于将表示为消息正文部分的任何字段,并将 ProtectionLevel 属性应用于 EncryptAndSign,如下面的示例所示。

    [MessageContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
    public class Company
    {
        [MessageHeader(ProtectionLevel = ProtectionLevel.Sign)]
        public string CompanyName;
    
        [MessageBodyMember(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
        public string CompanyID;
    }
    
    <MessageContract(ProtectionLevel:=ProtectionLevel.EncryptAndSign)> _
    Public Class Company
        <MessageHeader(ProtectionLevel:=ProtectionLevel.Sign)> _
        Public CompanyName As String
    
        <MessageBodyMember(ProtectionLevel:=ProtectionLevel.EncryptAndSign)> _
        Public CompanyID As String
    End Class
    

示例

下面的示例设置位于服务中不同位置的多个属性 (Attribute) 类的 ProtectionLevel 属性 (Property)。

[ServiceContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
public interface ICalculator
{
    [OperationContract(ProtectionLevel = ProtectionLevel.Sign)]
    double Add(double a, double b);

    [OperationContract()]
    [FaultContract(typeof(MathFault),
        ProtectionLevel = ProtectionLevel.EncryptAndSign)]
    double Subtract(double a, double b);

    [OperationContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
    Company GetCompanyInfo();
}

[DataContract]
public class MathFault
{
    [DataMember]
    public string operation;
    [DataMember]
    public string description;
}

[MessageContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
public class Company
{
    [MessageHeader(ProtectionLevel = ProtectionLevel.Sign)]
    public string CompanyName;

    [MessageBodyMember(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
    public string CompanyID;
}

[MessageContract(ProtectionLevel = ProtectionLevel.Sign)]
public class Calculator : ICalculator
{
    public double Add(double a, double b)
    {
        return a + b;
    }

    public double Subtract(double a, double b)
    {
        return a - b;
    }

    public Company GetCompanyInfo()
    {
        Company co = new Company();
        co.CompanyName = "www.cohowinery.com";
        return co;
    }
}

public class Test
{
    static void Main()
    {
        Test t = new Test();
        try
        {
            t.Run();
        }
        catch (System.InvalidOperationException inv)
        {
            Console.WriteLine(inv.Message);
        }
    }

    private void Run()
    {
        // Create a binding and set the security mode to Message.
        WSHttpBinding b = new WSHttpBinding();
        b.Security.Mode = SecurityMode.Message;

        Type contractType = typeof(ICalculator);
        Type implementedContract = typeof(Calculator);
        Uri baseAddress = new Uri("http://localhost:8044/base");

        // Create the ServiceHost and add an endpoint.
        ServiceHost sh = new ServiceHost(implementedContract, baseAddress);
        sh.AddServiceEndpoint(contractType, b, "Calculator");

        ServiceMetadataBehavior sm = new ServiceMetadataBehavior();
        sm.HttpGetEnabled = true;
        sh.Description.Behaviors.Add(sm);
        sh.Credentials.ServiceCertificate.SetCertificate(
            StoreLocation.CurrentUser,
            StoreName.My,
            X509FindType.FindByIssuerName,
            "ValidCertificateIssuer");

        foreach (ServiceEndpoint se in sh.Description.Endpoints)
        {
            ContractDescription cd = se.Contract;
            Console.WriteLine("\nContractDescription: ProtectionLevel = {0}", cd.Name, cd.ProtectionLevel);
            foreach (OperationDescription od in cd.Operations)
            {
                Console.WriteLine("\nOperationDescription: Name = {0}", od.Name, od.ProtectionLevel);
                Console.WriteLine("ProtectionLevel = {1}", od.Name, od.ProtectionLevel);
                foreach (MessageDescription m in od.Messages)
                {
                    Console.WriteLine("\t {0}: {1}", m.Action, m.ProtectionLevel);
                    foreach (MessageHeaderDescription mh in m.Headers)
                    {
                        Console.WriteLine("\t\t {0}: {1}", mh.Name, mh.ProtectionLevel);

                        foreach (MessagePropertyDescription mp in m.Properties)
                        {
                            Console.WriteLine("{0}: {1}", mp.Name, mp.ProtectionLevel);
                        }
                    }
                }
            }
        }
        sh.Open();
        Console.WriteLine("Listening");
        Console.ReadLine();
        sh.Close();
    }
}
<ServiceContract(ProtectionLevel:=ProtectionLevel.EncryptAndSign)> _
Public Interface ICalculator
    <OperationContract(ProtectionLevel:=ProtectionLevel.EncryptAndSign)> _
    Function Add(ByVal a As Double, ByVal b As Double) As Double


    <OperationContract(), _
       FaultContract _
       (GetType(MathFault), _
       Action:="http://localhost/Add", _
       Name:="AddFault", _
       Namespace:="http://contoso.com", _
       ProtectionLevel:=ProtectionLevel.EncryptAndSign)> _
    Function Subtract(ByVal a As Double, ByVal b As Double) As Double

    <OperationContract(ProtectionLevel:=ProtectionLevel.EncryptAndSign)> _
    Function GetCompanyInfo() As Company
End Interface


<DataContract()> _
Public Class MathFault
    <DataMember()> _
    Public operation As String
    <DataMember()> _
    Public description As String
End Class

<MessageContract(ProtectionLevel:=ProtectionLevel.EncryptAndSign)> _
Public Class Company
    <MessageHeader(ProtectionLevel:=ProtectionLevel.Sign)> _
    Public CompanyName As String

    <MessageBodyMember(ProtectionLevel:=ProtectionLevel.EncryptAndSign)> _
    Public CompanyID As String
End Class

<MessageContract(ProtectionLevel:=ProtectionLevel.Sign)> _
Public Class Calculator
    Implements ICalculator

    Public Function Add(ByVal a As Double, ByVal b As Double) As Double _
      Implements ICalculator.Add
        Return a + b

    End Function

    Public Function Subtract(ByVal a As Double, ByVal b As Double) As Double _
       Implements ICalculator.Subtract
        Return a - b

    End Function

    Public Function GetCompanyInfo() As Company Implements ICalculator.GetCompanyInfo
        Dim co As New Company()
        co.CompanyName = "www.cohowinery.com"
        Return co
    End Function
End Class


Public Class Test

    Shared Sub Main()
        Dim t As New Test()
        Try
            t.Run()
        Catch inv As System.InvalidOperationException
            Console.WriteLine(inv.Message)
        End Try
    End Sub


    Private Sub Run()
        ' Create a binding and set the security mode to Message.
        Dim b As New WSHttpBinding()
        b.Security.Mode = SecurityMode.Message

        Dim contractType As Type = GetType(ICalculator)
        Dim implementedContract As Type = GetType(Calculator)
        Dim baseAddress As New Uri("http://localhost:8044/base")

        ' Create the ServiceHost and add an endpoint.
        Dim sh As New ServiceHost(implementedContract, baseAddress)
        sh.AddServiceEndpoint(contractType, b, "Calculator")

        Dim sm As New ServiceMetadataBehavior()
        sm.HttpGetEnabled = True
        sh.Description.Behaviors.Add(sm)
        sh.Credentials.ServiceCertificate.SetCertificate( _
           StoreLocation.CurrentUser, StoreName.My, _
           X509FindType.FindByIssuerName, "ValidCertificateIssuer")

        Dim se As ServiceEndpoint
        For Each se In sh.Description.Endpoints
            Dim cd As ContractDescription = se.Contract
            Console.WriteLine(vbLf + "ContractDescription: ProtectionLevel = {0}", _
               cd.Name, cd.ProtectionLevel)
            Dim od As OperationDescription
            For Each od In cd.Operations
                Console.WriteLine(vbLf + "OperationDescription: Name = {0}", od.Name, od.ProtectionLevel)
                Console.WriteLine("ProtectionLevel = {1}", od.Name, od.ProtectionLevel)
                Dim m As MessageDescription
                For Each m In od.Messages
                    Console.WriteLine(vbTab + " {0}: {1}", m.Action, m.ProtectionLevel)
                    Dim mh As MessageHeaderDescription
                    For Each mh In m.Headers
                        Console.WriteLine(vbTab + vbTab + " {0}: {1}", mh.Name, mh.ProtectionLevel)

                        Dim mp As MessagePropertyDescription
                        For Each mp In m.Properties
                            Console.WriteLine("{0}: {1}", mp.Name, mp.ProtectionLevel)
                        Next mp
                    Next mh
                Next m
            Next od
        Next se
        sh.Open()
        Console.WriteLine("Listening")
        Console.ReadLine()
        sh.Close()

    End Sub
End Class

编译代码

下面的代码显示编译该示例代码所必需的命名空间。

using System;
using System.ServiceModel;
using System.Net.Security;
using System.ServiceModel.Description;
using System.Security.Cryptography.X509Certificates;
using System.Runtime.Serialization;
Imports System.ServiceModel
Imports System.Net.Security
Imports System.ServiceModel.Description
Imports System.Security.Cryptography.X509Certificates
Imports System.Runtime.Serialization

另请参阅