Procedura: impostare la proprietà ProtectionLevel

È possibile impostare il livello di protezione applicando un attributo appropriato e impostando la proprietà. È possibile impostare la protezione a livello di servizio su tutte le parti di ogni messaggio. In alternativa è possibile impostare la protezione a livelli granulari in modo crescente, dai metodi alle parti del messaggio. Per altre informazioni sulla proprietà ProtectionLevel, vedere Informazioni sul livello di protezione.

Nota

È possibile impostare i livelli di protezione solo nel codice, non nella configurazione.

Per firmare tutti i messaggi per un servizio

  1. Creare un'interfaccia per il servizio.

  2. Applicare l'attributo ServiceContractAttribute al servizio e impostare la proprietà ProtectionLevel su Sign, come illustrato nel codice seguente (il livello predefinito è 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
    

Per firmare tutte le parti del messaggio per un'operazione

  1. Creare un'interfaccia per il servizio e applicarvi l'attributo ServiceContractAttribute.

  2. Aggiungere una dichiarazione di metodo all'interfaccia.

  3. Applicare l'attributo OperationContractAttribute al metodo e impostare la proprietà ProtectionLevel su Sign, come illustrato nel codice seguente.

    // 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
    

Protezione dei messaggi di errore

È possibile inviare le eccezioni generate in un servizio a un client come errori SOAP. Per altre informazioni sulla creazione di errori fortemente tipizzati, vedere Impostazione e gestione degli errori nei contratti e nei servizi e Procedura: Dichiarare errori nei contratti di servizio.

Per proteggere i messaggi di errore

  1. Creare un tipo che rappresenta il messaggio di errore. Nell'esempio seguente viene creata una classe denominata MathFault con due campi.

  2. Applicare l'attributo DataContractAttribute al tipo e un attributo DataMemberAttribute a ogni campo che deve essere serializzato, come illustrato nel codice seguente.

    [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. Nell'interfaccia che restituirà l'errore, applicare l'attributo FaultContractAttribute al metodo che restituirà l'errore e impostare il parametro detailType sul tipo della classe di errore.

  4. Nel costruttore, inoltre, impostare la proprietà ProtectionLevel su EncryptAndSign, come illustrato nel codice seguente.

    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
    

Protezione delle parti del messaggio

Utilizzare un contratto di messaggio per proteggere le parti di un messaggio. Per altre informazioni sui contratti di messaggio, vedere Uso dei contratti di messaggio.

Per proteggere il corpo del messaggio

  1. Creare un tipo che rappresenta il messaggio. Nell'esempio seguente viene creata una classe Company con due campi, CompanyName e CompanyID.

  2. Applicare l'attributo MessageContractAttribute alla classe e impostare la proprietà ProtectionLevel su EncryptAndSign.

  3. Applicare l'attributo MessageHeaderAttribute a un campo che verrà espresso come intestazione del messaggio e impostare la proprietà ProtectionLevel su EncryptAndSign.

  4. Applicare l'elemento MessageBodyMemberAttribute a qualsiasi campo che sarà espresso come parte del corpo del messaggio e impostare la proprietà ProtectionLevel su EncryptAndSign, come illustrato nell'esempio seguente.

    [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
    

Esempio

Nell'esempio seguente viene impostata la proprietà ProtectionLevel di diverse classi Attribute in varie posizioni di un servizio.

[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

Compilazione del codice

Nel codice seguente vengono illustrati gli spazi dei nomi necessari per compilare il codice di esempio.

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

Vedi anche