Procedura: proteggere un servizio con credenziali di Windows
In questo argomento viene illustrato come attivare la protezione del trasferimento in un servizio Windows Communication Foundation (WCF) che risiede in un dominio di Windows e viene chiamato da client dello stesso dominio. Per ulteriori informazioni su su questo scenario, vedere Protezione del trasporto con l'autenticazione di Windows. Per un'applicazione di esempio, vedere l'esempio WSHttpBinding.
In questo argomento si presuppone la presenza di un'interfaccia e di un'implementazione del contratto esistente già definite, alle quali vengono aggiunti elementi. È inoltre possibile modificare un servizio e un client esistenti.
È possibile proteggere un servizio con credenziali di Windows completamente nel codice. In alternativa, è possibile omettere parte del codice tramite un file di configurazione. In questo argomento vengono illustrate entrambe le modalità. Accertarsi di utilizzare una sola modalità, non entrambe.
Nelle prime tre procedure viene illustrato come proteggere il servizio tramite il codice. Nella quarta e nella quinta procedura viene illustrato come eseguire questa operazione con un file di configurazione.
Utilizzo del codice
Il codice completo per il servizio e il client si trova nella sezione Esempio alla fine di questo argomento.
Nella prima procedura vengono illustrate la creazione e la configurazione di una classe WSHttpBinding nel codice. Per l'associazione viene utilizzata il trasporto HTTP. La stessa associazione viene utilizzata nel client.
Per creare un oggetto WSHttpBinding che utilizza le credenziali di Windows e la protezione dei messaggio
Il codice di questa procedura viene inserito all'inizio del metodo
Run
della classeTest
nel codice del servizio riportato nella sezione Esempio.Creare un'istanza della classe WSHttpBinding.
Impostare la proprietà Mode della classe WsHttpSecurity su Message.
Impostare la proprietà ClientCredentialType della classe MessageSecurityOverHttp su Windows.
Il codice per questa procedura è il seguente:
Dim myBinding As New WSHttpBinding() myBinding.Security.Mode = SecurityMode.Message myBinding.Security.Message.ClientCredentialType = MessageCredentialType.Windows
// First procedure: // create a WSHttpBinding that uses Windows credentials and message security WSHttpBinding myBinding = new WSHttpBinding(); myBinding.Security.Mode = SecurityMode.Message; myBinding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
Utilizzo dell'associazione in un servizio.
Si tratta della seconda procedura in cui viene illustrato l'utilizzo dell'associazione in un servizio indipendente. Per ulteriori informazioni su sui servizi di hosting vedere Servizi host.
Per utilizzare un'associazione in un servizio
Inserire il codice di questa procedura dopo il codice della procedura precedente.
Creare una variabile Type denominata
contractType
e assegnarle il tipo dell'interfaccia (ICalculator
). Quando si utilizza Visual Basic, utilizzare l'operatore GetType; quando si utilizza C#, utilizzare la parola chiave typeof.Creare una seconda variabile Type denominata
serviceType
e assegnarle il tipo del contratto implementato (Calculator
).Creare un'istanza della classe Uri denominata
baseAddress
con l'indirizzo di base del servizio. L'indirizzo di base deve avere uno schema corrispondente al trasporto. In questo caso lo schema di trasporto è HTTP e l'indirizzo include l'URI (Uniform Resource Identifier) speciale "localhost" e un numero di porta (8036), oltre a un indirizzo endpoint di base ("serviceModelSamples/): https://localhost:8036/serviceModelSamples/.Creare un'istanza della classe ServiceHost class con le variabili
serviceType
ebaseAddress
.Aggiungere un endpoint al servizio tramite l'interfaccia
contractType
, l'associazione e un nome di endpoint (secureCalculator). Un client deve concatenare l'indirizzo di base e il nome dell'endpoint quando avvia una chiamata al servizio.Chiamare il metodo Open per avviare il servizio. Il codice per questa procedura viene illustrato di seguito:
' Create the Type instances for later use and the URI for ' the base address. Dim contractType As Type = GetType(ICalculator) Dim serviceType As Type = GetType(Calculator) Dim baseAddress As New Uri("https://localhost:8036/serviceModelSamples/") ' Create the ServiceHost and add an endpoint, then start ' the service. Dim myServiceHost As New ServiceHost(serviceType, baseAddress) myServiceHost.AddServiceEndpoint(contractType, myBinding, "secureCalculator") myServiceHost.Open()
// 2nd Procedure: // Use the binding in a service // Create the Type instances for later use and the URI for // the base address. Type contractType = typeof(ICalculator); Type serviceType = typeof(Calculator); Uri baseAddress = new Uri("https://localhost:8036/SecuritySamples/"); // Create the ServiceHost and add an endpoint, then start // the service. ServiceHost myServiceHost = new ServiceHost(serviceType, baseAddress); myServiceHost.AddServiceEndpoint (contractType, myBinding, "secureCalculator"); //enable metadata ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; myServiceHost.Description.Behaviors.Add(smb); myServiceHost.Open();
Utilizzo dell'associazione in un client
In questa procedura viene illustrato come generare un proxy che comunica con il servizio. A tale scopo, viene utilizzato lo Strumento ServiceModel Metadata Utility Tool (Svcutil.exe) che crea il proxy servendosi dei metadati del servizio.
In questa procedura viene anche creata un'istanza della classe WSHttpBinding per comunicare con il servizio, quindi viene chiamato il servizio.
In questo esempio, per creare il client viene utilizzato solo codice. In alternativa, è possibile utilizzare un file di configurazione, illustrato nella sezione successiva a questa procedura.
Per utilizzare un'associazione in un client con codice
Utilizzare lo strumento SvcUtil.exe per generare il codice del proxy tramite i metadati del servizio. Per ulteriori informazioni, vedere Procedura: creare un client di Windows Communication Foundation. Il codice proxy generato eredita dalla classe ClientBase, che assicura che ogni client disponga delle proprietà, dei costruttori e dei metodi necessari per comunicare con un servizio WCF. In questo esempio, il codice generato include la classe
CalculatorClient
che implementa l'interfacciaICalculator
, consentendo la compatibilità con il codice del servizio.Il codice di questa procedura viene inserito all'inizio del metodo
Main
del programma client.Creare un'istanza della classe WSHttpBinding e impostarne la modalità di sicurezza su Message e il tipo di credenziale client su Windows. Nell'esempio viene denominata la variabile
clientBinding
.Creare un'istanza della classe EndpointAddress denominata
serviceAddress
. Inizializzare l'istanza con l'indirizzo di base concatenato al nome dell'endpoint.Creare un'istanza della classe client generata con le variabili
serviceAddress
eclientBinding
.Chiamare il metodo Open, come mostrato nel codice seguente.
Chiamare il servizio e visualizzare i risultati.
Dim b As New WSHttpBinding(SecurityMode.Message) b.Security.Message.ClientCredentialType = MessageCredentialType.Windows Dim ea As New EndpointAddress("net.tcp://machinename:8036/endpoint") Dim cc As New CalculatorClient(b, ea) cc.Open() ' Alternatively, use a binding name from a configuration file generated by the ' SvcUtil.exe tool to create the client. Omit the binding and endpoint address ' because that information is provided by the configuration file. ' CalculatorClass cc = new CalculatorClient("ICalculator_Binding")
// 3rd Procedure: // Creating a binding and using it in a service // To run using config, comment the following lines, and uncomment out the code // following this section WSHttpBinding b = new WSHttpBinding(SecurityMode.Message); b.Security.Message.ClientCredentialType = MessageCredentialType.Windows; EndpointAddress ea = new EndpointAddress("Http://localhost:8036/SecuritySamples/secureCalculator"); CalculatorClient cc = new CalculatorClient(b, ea); cc.Open(); // Now call the service and display the results // Call the Add service operation. double value1 = 100.00D; double value2 = 15.99D; double result = cc.Add(value1, value2); Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result); // Closing the client gracefully closes the connection and cleans up resources. cc.Close();
Utilizzo del file di configurazione
Anziché creare l'associazione con codice procedurale, è possibile utilizzare il codice seguente illustrato per la sezione dell'associazione del file di configurazione.
Se non si dispone già di un servizio definito, vedere Progettazione e implementazione di servizi e Configurazione dei servizi.
Nota Questo codice di configurazione viene utilizzato nei file di configurazione del servizio e del client.
Per abilitare la protezione del trasferimento in un servizio in un dominio Windows utilizzando la configurazione
Aggiungere un elemento <wsHttpBinding><bindings> alla sezione dell'elemento del file di configurazione.
Aggiungere un elemento <binding> all'elemento <WSHttpBinding> e impostare l'attributo configurationName su un valore appropriato all'applicazione.
Aggiungere un elemento <security> e impostare l'attributo mode su Message.
Aggiungere un elemento <message> e impostare l'attributo clientCredentialType su Windows.
Nel file di configurazione del servizio, sostituire la sezione <bindings> con il codice seguente. Se non si dispone già di un file di configurazione del servizio, vedere Utilizzo di associazioni per configurare servizi e client.
<bindings> <wsHttpBinding> <binding name = "wsHttpBinding_Calculator"> <security mode="Message"> <message clientCredentialType="Windows"/> </security> </binding> </wsHttpBinding> </bindings>
Utilizzo dell'associazione in un client
In questa procedura viene illustrato come generare due file, un proxy che comunica con il servizio e un file di configurazione. Vengono inoltre descritte le modifiche apportate al programma client, ovvero il terzo file utilizzato nel client.
Per utilizzare un'associazione in un client con configurazione
Utilizzare lo strumento SvcUtil.exe per generare il codice proxy e il file di configurazione tramite i metadati del servizio. Per ulteriori informazioni, vedere Procedura: creare un client di Windows Communication Foundation.
Sostituire la sezione <Bindings> del file di configurazione generato con il codice di configurazione della sezione precedente.
Il codice procedurale viene inserito all'inizio del metodo
Main
del programma client.Creare un'istanza della classe client generata che passi il nome dell'associazione nel file di configurazione come parametro di input.
Chiamare il metodo Open, come mostrato nel codice seguente.
Chiamare il servizio e visualizzare i risultati.
// 4th Procedure: // Using config instead of the binding-related code // In this case, use a binding name from a configuration file generated by the // SvcUtil.exe tool to create the client. Omit the binding and endpoint address // because that information is provided by the configuration file. CalculatorClient cc = new CalculatorClient("ICalculator_Binding"); cc.Open(); // Now call the service and display the results // Call the Add service operation. double value1 = 100.00D; double value2 = 15.99D; double result = cc.Add(value1, value2); Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result); // Closing the client gracefully closes the connection and cleans up resources. cc.Close();
Esempio
using System;
using System.Collections;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Security.Permissions;
[assembly: SecurityPermission(SecurityAction.RequestMinimum, Execution = true)]
namespace Microsoft.Security.Samples
{
public class Test
{
static void Main()
{
Test t = new Test();
Console.WriteLine("Starting....");
t.Run();
}
private void Run()
{
// First procedure:
// create a WSHttpBinding that uses Windows credentials and message security
WSHttpBinding myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Message;
myBinding.Security.Message.ClientCredentialType =
MessageCredentialType.Windows;
// 2nd Procedure:
// Use the binding in a service
// Create the Type instances for later use and the URI for
// the base address.
Type contractType = typeof(ICalculator);
Type serviceType = typeof(Calculator);
Uri baseAddress = new
Uri("https://localhost:8036/SecuritySamples/");
// Create the ServiceHost and add an endpoint, then start
// the service.
ServiceHost myServiceHost =
new ServiceHost(serviceType, baseAddress);
myServiceHost.AddServiceEndpoint
(contractType, myBinding, "secureCalculator");
//enable metadata
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
myServiceHost.Description.Behaviors.Add(smb);
myServiceHost.Open();
Console.WriteLine("Listening");
Console.WriteLine("Press Enter to close the service");
Console.ReadLine();
myServiceHost.Close();
}
}
[ServiceContract]
public interface ICalculator
{
[OperationContract]
double Add(double a, double b);
}
public class Calculator : ICalculator
{
public double Add(double a, double b)
{
return a + b;
}
}
}
Vedere anche
Attività
Procedura: creare un client di Windows Communication Foundation
Riferimento
Concetti
Strumento ServiceModel Metadata Utility Tool (Svcutil.exe)
Protezione dei servizi
Cenni preliminari sulla sicurezza