WCF Güvenliğini Programlama
Bu konu, güvenli bir Windows Communication Foundation (WCF) uygulaması oluşturmak için kullanılan temel programlama görevlerini açıklar. Bu konu yalnızca aktarım güvenliği olarak bilinen kimlik doğrulama, gizlilik ve bütünlük konularını kapsar. Bu konu yetkilendirmeyi (kaynaklara veya hizmetlere erişimin denetimi) kapsamaz; yetkilendirme hakkında bilgi için bkz . Yetkilendirme.
Not
Özellikle WCF ile ilgili güvenlik kavramlarına değerli bir giriş için Msdn'deki Senaryolar, Desenler ve Web Hizmetleri Geliştirmeleri için Uygulama Kılavuzu (WSE) 3.0'daki desen ve uygulama öğreticileri kümesine bakın.
WCF güvenliğini programlamak için şu üç adım ayarlanır: güvenlik modu, istemci kimlik bilgisi türü ve kimlik bilgisi değerleri. Bu adımları kod veya yapılandırma aracılığıyla gerçekleştirebilirsiniz.
Güvenlik Modunu Ayarlama
Aşağıda WCF'de güvenlik moduyla programlamaya yönelik genel adımlar açıklanmaktadır:
Uygulama gereksinimlerinize uygun önceden tanımlanmış bağlamalardan birini seçin. Bağlama seçeneklerinin listesi için bkz . Sistem Tarafından Sağlanan Bağlamalar. Varsayılan olarak, neredeyse her bağlamada güvenlik etkindir. Tek özel durum sınıfıdır BasicHttpBinding (yapılandırma kullanılarak <temelHttpBinding>).
Seçtiğiniz bağlama taşımayı belirler. Örneğin, WSHttpBinding aktarım olarak HTTP kullanır; NetTcpBinding TCP kullanır.
Bağlama için güvenlik modlarından birini seçin. Seçtiğiniz bağlamanın kullanılabilir mod seçeneklerini belirlediğini unutmayın. Örneğin , aktarım güvenliğine WSDualHttpBinding izin vermez (bu bir seçenek değildir). Benzer şekilde, ne ve MsmqIntegrationBinding ne de ileti güvenliğine NetNamedPipeBinding izin verir.
Üç seçeneğiniz vardır:
Transport
Aktarım güvenliği, seçtiğiniz bağlamanın kullandığı mekanizmaya bağlıdır. Örneğin, kullanıyorsanız
WSHttpBinding
güvenlik mekanizması Güvenli Yuva Katmanı (SSL) (HTTPS protokolü için de mekanizmadır). Genel olarak ifade etmek gerekirse, aktarım güvenliğinin temel avantajı, hangi taşımayı kullanırsanız kullansanız da iyi aktarım hızı sağlamasıdır. Ancak iki sınırlaması vardır: Birincisi, aktarım mekanizmasının bir kullanıcının kimliğini doğrulamak için kullanılan kimlik bilgisi türünü dikte ettirmesidir. Bu, yalnızca bir hizmetin farklı kimlik bilgileri gerektiren diğer hizmetlerle birlikte çalışabilmesi gerektiğinde bir dezavantajdır. İkincisi, güvenlik ileti düzeyinde uygulanmadığından güvenliğin uçtan uca değil atlamalı olarak uygulanmasıdır. Bu ikinci sınırlama yalnızca istemci ve hizmet arasındaki ileti yolu aracılar içeriyorsa bir sorundur. Hangi taşımanın kullanılacağı hakkında daha fazla bilgi için bkz . Taşıma Seçme. Aktarım güvenliğini kullanma hakkında daha fazla bilgi için bkz . Aktarım Güvenliğine Genel Bakış.Message
İleti güvenliği, her iletinin iletinin güvenliğini sağlamak için gerekli üst bilgileri ve verileri içerdiği anlamına gelir. Üst bilgilerin bileşimi farklılık gösterdiğinden, istediğiniz sayıda kimlik bilgisi ekleyebilirsiniz. Aktarım mekanizmasının sağlayabildiği belirli bir kimlik bilgisi türünü talep eden diğer hizmetlerle birlikte çalışırsanız veya iletinin her hizmetin farklı bir kimlik bilgisi türü talep ettiği birden fazla hizmetle kullanılması gerekiyorsa bu bir faktör haline gelir.
Daha fazla bilgi için bkz . İleti Güvenliği.
TransportWithMessageCredential
Bu seçim, ileti aktarımını güvenli hale getirmek için aktarım katmanını kullanırken, her ileti diğer hizmetlerin ihtiyaç duyduğu zengin kimlik bilgilerini içerir. Bu, aktarım güvenliğinin performans avantajını ileti güvenliğinin zengin kimlik bilgileri avantajıyla birleştirir. Bu, şu bağlamalarla kullanılabilir: BasicHttpBinding, WSFederationHttpBinding, NetPeerTcpBindingve WSHttpBinding.
HTTP (başka bir deyişle HTTPS) için aktarım güvenliğini kullanmaya karar verirseniz, konağı bir SSL sertifikasıyla yapılandırmanız ve bir bağlantı noktasında SSL'yi etkinleştirmeniz gerekir. Daha fazla bilgi için bkz . HTTP Aktarım Güvenliği.
kullanıyorsanız WSHttpBinding ve güvenli bir oturum oluşturmanız gerekmiyorsa özelliğini olarak
false
ayarlayınEstablishSecurityContext.bir istemci ve hizmet simetrik anahtar kullanarak bir kanal oluşturduğunda güvenli oturum oluşur (hem istemci hem de sunucu iletişim kutusu kapatılana kadar konuşmanın uzunluğu için aynı anahtarı kullanır).
İstemci Kimlik Bilgisi Türünü Ayarlama
Uygun bir istemci kimlik bilgisi türü seçin. Daha fazla bilgi için bkz . Kimlik Bilgisi Türü Seçme. Aşağıdaki istemci kimlik bilgisi türleri kullanılabilir:
Windows
Certificate
Digest
Basic
UserName
NTLM
IssuedToken
Modu nasıl ayarladığınıza bağlı olarak, kimlik bilgisi türünü ayarlamanız gerekir. Örneğin, öğesini seçtiyseniz wsHttpBinding
ve modu "İleti" olarak ayarladıysanız, message öğesinin özniteliğini aşağıdaki değerlerden birine de ayarlayabilirsiniz clientCredentialType
: None
, Windows
, UserName
, Certificate
ve , ve IssuedToken
, aşağıdaki yapılandırma örneğinde gösterildiği gibi.
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="myBinding">
<security mode="Message"/>
<message clientCredentialType="Windows"/>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
Veya kodda:
WSHttpBinding b = new WSHttpBinding();
b.Name = "myBinding";
b.Security.Mode = SecurityMode.Message;
b.Security.Message.ClientCredentialType=MessageCredentialType.Windows;
Dim b As New WSHttpBinding()
b.Name = "myBinding"
b.Security.Mode = SecurityMode.Message
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows
Hizmet Kimlik Bilgisi Değerlerini Ayarlama
Bir istemci kimlik bilgisi türü seçtikten sonra, hizmetin ve istemcinin kullanması için gerçek kimlik bilgilerini ayarlamanız gerekir. Hizmette kimlik bilgileri sınıfı kullanılarak ServiceCredentials ayarlanır ve sınıfının özelliği ServiceHostBase tarafından Credentials döndürülür. Kullanımdaki bağlama hizmet kimlik bilgisi türünü, seçilen güvenlik modunu ve istemci kimlik bilgilerinin türünü ifade eder. Aşağıdaki kod, hizmet kimlik bilgileri için bir sertifika ayarlar.
// Create the binding for an endpoint.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.Message;
// Create the ServiceHost for a calculator.
Uri baseUri = new Uri("net.tcp://MachineName/tcpBase");
Uri[] baseAddresses = new Uri[] { baseUri };
ServiceHost sh = new ServiceHost(typeof(Calculator), baseAddresses);
// Add an endpoint using the binding and a new address.
Type c = typeof(ICalculator);
sh.AddServiceEndpoint(c, b, "MyEndpoint");
// Set a certificate as the credential for the service.
sh.Credentials.ServiceCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName,
"client.com");
try
{
sh.Open();
Console.WriteLine("Listening....");
Console.ReadLine();
sh.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("A communication error occurred: {0}", ce.Message);
Console.WriteLine();
}
catch (System.Exception exc)
{
Console.WriteLine("An unforeseen error occurred: {0}", exc.Message);
Console.ReadLine();
}
' Create the binding for an endpoint.
Dim b As New NetTcpBinding()
b.Security.Mode = SecurityMode.Message
' Create the ServiceHost for a calculator.
Dim baseUri As New Uri("net.tcp://MachineName/tcpBase")
Dim baseAddresses() As Uri = {baseUri}
Dim sh As New ServiceHost(GetType(Calculator), baseAddresses)
' Add an endpoint using the binding and a new address.
Dim c As Type = GetType(ICalculator)
sh.AddServiceEndpoint(c, b, "MyEndpoint")
' Set a certificate as the credential for the service.
sh.Credentials.ServiceCertificate.SetCertificate( _
StoreLocation.LocalMachine, _
StoreName.My, _
X509FindType.FindBySubjectName, _
"contoso.com")
Try
sh.Open()
Console.WriteLine("Listening....")
Console.ReadLine()
sh.Close()
Catch ce As CommunicationException
Console.WriteLine("A communication error occurred: {0}", ce.Message)
Console.WriteLine()
Catch exc As System.Exception
Console.WriteLine("An unforeseen error occurred: {0}", exc.Message)
Console.ReadLine()
End Try
İstemci Kimlik Bilgisi Değerlerini Ayarlama
İstemcide, sınıfını ClientCredentials kullanarak istemci kimlik bilgisi değerlerini ayarlayın ve sınıfının özelliği ClientBase<TChannel> tarafından ClientCredentials döndürülür. Aşağıdaki kod, TCP protokolunu kullanarak istemcide kimlik bilgisi olarak bir sertifika ayarlar.
// Create a NetTcpBinding and set its security properties. The
// security mode is Message, and the client must be authenticated with
// Windows. Therefore the client must be on the same Windows domain.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.Message;
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
// Set a Type variable for use when constructing the endpoint.
Type c = typeof(ICalculator);
// Create a base address for the service.
Uri tcpBaseAddress =
new Uri("net.tcp://machineName.Domain.Contoso.com:8036/serviceName");
// The base address is in an array of URI objects.
Uri[] baseAddresses = new Uri[] { tcpBaseAddress };
// Create the ServiceHost with type and base addresses.
ServiceHost sh = new ServiceHost(typeof(CalculatorClient), baseAddresses);
// Add an endpoint to the service using the service type and binding.
sh.AddServiceEndpoint(c, b, "");
sh.Open();
string address = sh.Description.Endpoints[0].ListenUri.AbsoluteUri;
Console.WriteLine("Listening @ {0}", address);
Console.WriteLine("Press enter to close the service");
Console.ReadLine();
' Create a NetTcpBinding and set its security properties. The
' security mode is Message, and the client must be authenticated with
' Windows. Therefore the client must be on the same Windows domain.
Dim b As New NetTcpBinding()
b.Security.Mode = SecurityMode.Message
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows
' Set a Type variable for use when constructing the endpoint.
Dim c As Type = GetType(ICalculator)
' Create a base address for the service.
Dim tcpBaseAddress As New Uri("net.tcp://machineName.Domain.Contoso.com:8036/serviceName")
' The base address is in an array of URI objects.
Dim baseAddresses() As Uri = {tcpBaseAddress}
' Create the ServiceHost with type and base addresses.
Dim sh As New ServiceHost(GetType(CalculatorClient), baseAddresses)
' Add an endpoint to the service using the service type and binding.
sh.AddServiceEndpoint(c, b, "")
sh.Open()
Dim address As String = sh.Description.Endpoints(0).ListenUri.AbsoluteUri
Console.WriteLine("Listening @ {0}", address)
Console.WriteLine("Press enter to close the service")
Console.ReadLine()