X.509 Sertifika Doğrulayıcı
Bu örnek, özel bir X.509 Sertifika Doğrulayıcı'nın nasıl uygulanduğunu gösterir. Bu, yerleşik X.509 Sertifika Doğrulama modlarından hiçbirinin uygulama gereksinimlerine uygun olmadığı durumlarda kullanışlıdır. Bu örnek, kendi kendine verilen sertifikaları kabul eden özel bir doğrulayıcıya sahip olan bir hizmeti gösterir. İstemci, hizmette kimlik doğrulaması yapmak için böyle bir sertifika kullanır.
Not: Herkes kendi kendine verilen bir sertifika oluşturaabildiği için, hizmet tarafından kullanılan özel doğrulayıcı ChainTrust X509CertificateValidationMode tarafından sağlanan varsayılan davranıştan daha az güvenlidir. Bu doğrulama mantığını üretim kodunda kullanmadan önce bunun güvenlik etkileri dikkatli bir şekilde dikkate alınmalıdır.
Özetle, bu örnek aşağıdakilerin nasıl yapıldığını gösterir:
İstemcinin kimliği bir X.509 sertifikası kullanılarak doğrulanabilir.
Sunucu, istemci kimlik bilgilerini özel bir X509CertificateValidator ile doğrular.
Sunucunun kimliği, sunucunun X.509 sertifikası kullanılarak doğrulanır.
Hizmet, App.config yapılandırma dosyası kullanılarak tanımlanan, hizmetle iletişim kurmak için tek bir uç nokta sunar. Uç nokta bir adres, bağlama ve sözleşmeden oluşur. Bağlama, varsayılan olarak ve istemci sertifikası kimlik doğrulaması kullanan WSSecurity
bir standartla wsHttpBinding
yapılandırılır. Hizmet davranışı, istemci X.509 sertifikalarını doğrulamak için Özel modu ve doğrulayıcı sınıfının türünü belirtir. Davranış ayrıca serviceCertificate öğesini kullanarak sunucu sertifikasını belirtir. Sunucu sertifikasının serviceCertificate içindeki ile aynı değeri SubjectName
findValue
içermesi gerekir>.<
<system.serviceModel>
<services>
<service name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<!-- use host/baseAddresses to configure base address -->
<!-- provided by host -->
<host>
<baseAddresses>
<add baseAddress =
"http://localhost:8001/servicemodelsamples/service" />
</baseAddresses>
</host>
<!-- use base address specified above, provide one endpoint -->
<endpoint address="certificate"
binding="wsHttpBinding"
bindingConfiguration="Binding"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
</service>
</services>
<bindings>
<wsHttpBinding>
<!-- X509 certificate binding -->
<binding name="Binding">
<security mode="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceDebug includeExceptionDetailInFaults ="true"/>
<serviceCredentials>
<!-- The serviceCredentials behavior allows one -->
<!-- to specify authentication constraints on -->
<!-- client certificates. -->
<clientCertificate>
<!-- Setting the certificateValidationMode to -->
<!-- Custom means that if the custom -->
<!-- X509CertificateValidator does NOT throw -->
<!-- an exception, then the provided certificate -->
<!-- will be trusted without performing any -->
<!-- validation beyond that performed by the custom -->
<!-- validator. The security implications of this -->
<!-- setting should be carefully considered before -->
<!-- using Custom in production code. -->
<authentication
certificateValidationMode="Custom"
customCertificateValidatorType =
"Microsoft.ServiceModel.Samples.CustomX509CertificateValidator, service" />
</clientCertificate>
<!-- The serviceCredentials behavior allows one to -->
<!-- define a service certificate. -->
<!-- A service certificate is used by a client to -->
<!-- authenticate the service and provide message -->
<!-- protection. This configuration references the -->
<!-- "localhost" certificate installed during the setup -->
<!-- instructions. -->
<serviceCertificate findValue="localhost"
storeLocation="LocalMachine"
storeName="My" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
İstemci uç noktası yapılandırması bir yapılandırma adı, hizmet uç noktası için mutlak bir adres, bağlama ve sözleşmeden oluşur. İstemci bağlaması uygun mod ve iletisiyle clientCredentialType
yapılandırılır.
<system.serviceModel>
<client>
<!-- X509 certificate based endpoint -->
<endpoint name="Certificate"
address=
"http://localhost:8001/servicemodelsamples/service/certificate"
binding="wsHttpBinding"
bindingConfiguration="Binding"
behaviorConfiguration="ClientCertificateBehavior"
contract="Microsoft.ServiceModel.Samples.ICalculator">
</endpoint>
</client>
<bindings>
<wsHttpBinding>
<!-- X509 certificate binding -->
<binding name="Binding">
<security mode="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertificateBehavior">
<clientCredentials>
<serviceCertificate>
<!-- Setting the certificateValidationMode to -->
<!-- PeerOrChainTrust means that if the certificate -->
<!-- is in the user's Trusted People store, then it -->
<!-- is trusted without performing a validation of -->
<!-- the certificate's issuer chain. -->
<!-- This setting is used here for convenience so -->
<!-- that the sample can be run without having to -->
<!-- have certificates issued by a certification -->
<!-- authority (CA). This setting is less secure -->
<!-- than the default, ChainTrust. The security -->
<!-- implications of this setting should be -->
<!-- carefully considered before using -->
<!-- PeerOrChainTrust in production code.-->
<authentication
certificateValidationMode="PeerOrChainTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
İstemci uygulaması, kullanılacak istemci sertifikasını ayarlar.
// Create a client with Certificate endpoint configuration
CalculatorClient client = new CalculatorClient("Certificate");
try
{
client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "test1");
// Call the Add service operation.
double value1 = 100.00D;
double value2 = 15.99D;
double result = client.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
// Call the Subtract service operation.
value1 = 145.00D;
value2 = 76.54D;
result = client.Subtract(value1, value2);
Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);
// Call the Multiply service operation.
value1 = 9.00D;
value2 = 81.25D;
result = client.Multiply(value1, value2);
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
// Call the Divide service operation.
value1 = 22.00D;
value2 = 7.00D;
result = client.Divide(value1, value2);
Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
client.Close();
}
catch (TimeoutException e)
{
Console.WriteLine("Call timed out : {0}", e.Message);
client.Abort();
}
catch (CommunicationException e)
{
Console.WriteLine("Call failed : {0}", e.Message);
client.Abort();
}
catch (Exception e)
{
Console.WriteLine("Call failed : {0}", e.Message);
client.Abort();
}
Bu örnek sertifikaları doğrulamak için özel bir X509CertificateValidator kullanır. Örnek, adresinden X509CertificateValidatortüretilen CustomX509CertificateValidator'ı uygular. Daha fazla bilgi için hakkında X509CertificateValidator belgelere bakın. Bu özel doğrulayıcı örneği, aşağıdaki kodda gösterildiği gibi kendi kendine verilen herhangi bir X.509 sertifikasını kabul etmek için Validate yöntemini uygular.
public class CustomX509CertificateValidator : X509CertificateValidator
{
public override void Validate ( X509Certificate2 certificate )
{
// Only accept self-issued certificates
if (certificate.Subject != certificate.Issuer)
throw new Exception("Certificate is not self-issued");
}
}
Doğrulayıcı hizmet koduna uygulandıktan sonra, hizmet konağı kullanılacak doğrulayıcı örneği hakkında bilgilendirilmelidir. Bu işlem aşağıdaki kod kullanılarak yapılır.
serviceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom;
serviceHost.Credentials.ClientCertificate.Authentication.CustomCertificateValidator = new CustomX509CertificateValidator();
Veya yapılandırmada aşağıdaki gibi aynı şeyi yapabilirsiniz.
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
...
<serviceCredentials>
<!--The serviceCredentials behavior allows one to specify -->
<!--authentication constraints on client certificates.-->
<clientCertificate>
<!-- Setting the certificateValidationMode to Custom means -->
<!--that if the custom X509CertificateValidator does NOT -->
<!--throw an exception, then the provided certificate will -->
<!--be trusted without performing any validation beyond that -->
<!--performed by the custom validator. The security -->
<!--implications of this setting should be carefully -->
<!--considered before using Custom in production code. -->
<authentication certificateValidationMode="Custom"
customCertificateValidatorType =
"Microsoft.ServiceModel.Samples. CustomX509CertificateValidator, service" />
</clientCertificate>
</serviceCredentials>
...
</behavior>
</serviceBehaviors>
</behaviors>
Örneği çalıştırdığınızda, işlem istekleri ve yanıtları istemci konsolu penceresinde görüntülenir. İstemcinin tüm yöntemleri başarıyla çağırması gerekir. İstemciyi kapatmak için istemci penceresinde ENTER tuşuna basın.
Batch Dosyasını Ayarlama
Bu örneğe dahil edilen Setup.bat toplu iş dosyası, sunucuyu ilgili sertifikalarla yapılandırarak sunucu sertifikası tabanlı güvenlik gerektiren şirket içinde barındırılan bir uygulama çalıştırmanızı sağlar. Bu toplu iş dosyası, bilgisayarlar arasında çalışacak veya barındırılmayan bir durumda çalışacak şekilde değiştirilmelidir.
Aşağıda, toplu iş dosyalarının farklı bölümlerine ilişkin kısa bir genel bakış sağlanır; böylece bunlar uygun yapılandırmada çalışacak şekilde değiştirilebilir:
Sunucu sertifikası oluşturuluyor:
Setup.bat toplu iş dosyasındaki aşağıdaki satırlar kullanılacak sunucu sertifikasını oluşturur. %SERVER_NAME% değişkeni sunucu adını belirtir. Kendi sunucu adınızı belirtmek için bu değişkeni değiştirin. Varsayılan değer localhost'tır.
echo ************ echo Server cert setup starting echo %SERVER_NAME% echo ************ echo making server cert echo ************ makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
Sunucu sertifikasını istemcinin güvenilen sertifika deposuna yükleme:
Setup.bat toplu iş dosyasındaki aşağıdaki satırlar sunucu sertifikasını istemcinin güvenilen kişiler deposuna kopyalar. Makecert.exe tarafından oluşturulan sertifikalara istemci sistemi tarafından örtük olarak güvenilmediğinden bu adım gereklidir. İstemci güvenilen kök sertifikasında (örneğin, Microsoft tarafından verilen bir sertifika) köke sahip bir sertifikanız zaten varsa, istemci sertifika depoyu sunucu sertifikasıyla doldurma adımı gerekli değildir.
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
İstemci sertifikası oluşturuluyor:
Setup.bat toplu iş dosyasındaki aşağıdaki satırlar kullanılacak istemci sertifikasını oluşturur. %USER_NAME% değişkeni istemci adını belirtir. İstemci kodunun aradığı ad olduğundan bu değer "test1" olarak ayarlanır. %USER_NAME% değerini değiştirirseniz, Client.cs kaynak dosyasında karşılık gelen değeri değiştirmeniz ve istemciyi yeniden oluşturmanız gerekir.
Sertifika, CurrentUser deposu konumu altında My (Personal) deposunda depolanır.
echo ************ echo Client cert setup starting echo %USER_NAME% echo ************ echo making client cert echo ************ makecert.exe -sr CurrentUser -ss MY -a sha1 -n CN=%USER_NAME% -sky exchange -pe
İstemci sertifikasını sunucunun güvenilen sertifika deposuna yükleme:
Setup.bat toplu iş dosyasındaki aşağıdaki satırlar istemci sertifikasını güvenilen kişiler deposuna kopyalar. Makecert.exe tarafından oluşturulan sertifikalara sunucu sistemi tarafından örtük olarak güvenilmediğinden bu adım gereklidir. Güvenilir bir kök sertifikaya (örneğin, Microsoft tarafından verilen bir sertifikaya) sahip bir sertifikanız zaten varsa, sunucu sertifika depoyu istemci sertifikasıyla doldurma adımı gerekli değildir.
certmgr.exe -add -r CurrentUser -s My -c -n %USER_NAME% -r LocalMachine -s TrustedPeople
Örneği ayarlamak ve derlemek için
Çözümü oluşturmak için Windows Communication Foundation Örnekleri Oluşturma başlığındaki yönergeleri izleyin.
Örneği tek veya bilgisayarlar arası bir yapılandırmada çalıştırmak için aşağıdaki yönergeleri kullanın.
Örneği aynı bilgisayarda çalıştırmak için
Yönetici ayrıcalıklarıyla açılan bir Visual Studio komut istemi içindeki örnek yükleme klasöründen Setup.bat çalıştırın. Bu, örneği çalıştırmak için gereken tüm sertifikaları yükler.
Önemli
Setup.bat toplu iş dosyası, Visual Studio Komut İsteminden çalıştırılacak şekilde tasarlanmıştır. Visual Studio Komut İstemi içinde ayarlanan PATH ortam değişkeni, Setup.bat betiği tarafından gereken yürütülebilir dosyaları içeren dizine işaret eder.
service\bin'den Service.exe başlatın.
\client\bin konumundan Client.exe başlatın. İstemci etkinliği, istemci konsol uygulamasında görüntülenir.
İstemci ve hizmet iletişim kuramıyorsa bkz. WCF Örnekleri için sorun giderme İpuçları.
Örneği bilgisayarlar arasında çalıştırmak için
Hizmet bilgisayarında bir dizin oluşturun.
Hizmet programı dosyalarını \service\bin dosyasından hizmet bilgisayarındaki sanal dizine kopyalayın. Ayrıca Setup.bat, Cleanup.bat, GetComputerName.vbs ve ImportClientCert.bat dosyalarını hizmet bilgisayarına kopyalayın.
İstemci ikili dosyaları için istemci bilgisayarda bir dizin oluşturun.
İstemci programı dosyalarını istemci bilgisayardaki istemci dizinine kopyalayın. Ayrıca Setup.bat, Cleanup.bat ve ImportServiceCert.bat dosyalarını istemciye kopyalayın.
Sunucuda, yönetici ayrıcalıklarıyla açılan Visual Studio için Geliştirici Komut İstemi'nde komutunu çalıştırın
setup.bat service
. bağımsız değişkeniyleservice
çalıştırmaksetup.bat
, bilgisayarın tam etki alanı adına sahip bir hizmet sertifikası oluşturur ve hizmet sertifikasını Service.cer adlı bir dosyaya aktarır.Service.exe.config dosyasını, bilgisayarın tam etki alanı adıyla aynı olan yeni sertifika adını (
findValue
serviceCertificate> özniteliğinde<) yansıtacak şekilde düzenleyin. Ayrıca service>/<baseAddresses> öğesindeki <bilgisayar adını localhost'tan hizmet bilgisayarınızın tam adı olarak değiştirin.Service.cer dosyasını hizmet dizininden istemci bilgisayardaki istemci dizinine kopyalayın.
İstemcide, yönetici ayrıcalıklarıyla açılan Visual Studio için Geliştirici Komut İstemi'nde komutunu çalıştırın
setup.bat client
. bağımsız değişkeniyleclient
çalıştırmaksetup.bat
client.com adlı bir istemci sertifikası oluşturur ve istemci sertifikasını Client.cer adlı bir dosyaya aktarır.İstemci bilgisayardaki Client.exe.config dosyasında, uç noktanın adres değerini hizmetinizin yeni adresiyle eşleşecek şekilde değiştirin. Bunu yapmak için localhost yerine sunucunun tam etki alanı adını yazın.
Client.cer dosyasını istemci dizininden sunucudaki hizmet dizinine kopyalayın.
İstemcide, yönetici ayrıcalıklarıyla açılan Visual Studio için Geliştirici Komut İstemi'nde ImportServiceCert.bat çalıştırın. Bu, hizmet sertifikasını Service.cer dosyasından CurrentUser - Trusted Kişiler deposuna aktarır.
Sunucuda, yönetici ayrıcalıklarıyla açılan Visual Studio için Geliştirici Komut İstemi'nde ImportClientCert.bat çalıştırın. Bu, istemci sertifikasını Client.cer dosyasından LocalMachine - Trusted Kişiler deposuna aktarır.
Sunucu bilgisayarında, komut istemi penceresinden Service.exe başlatın.
İstemci bilgisayarda, bir komut istemi penceresinden Client.exe başlatın. İstemci ve hizmet iletişim kuramıyorsa bkz. WCF Örnekleri için sorun giderme İpuçları.
Örnekten sonra temizlemek için
- Örneği çalıştırmayı bitirdikten sonra örnekler klasöründe Cleanup.bat çalıştırın. Bu, sunucu ve istemci sertifikalarını sertifika deposundan kaldırır.
Not
Bu betik, bu örneği bilgisayarlar arasında çalıştırırken istemcideki hizmet sertifikalarını kaldırmaz. Bilgisayarlar arasında sertifika kullanan Windows Communication Foundation (WCF) örnekleri çalıştırdıysanız CurrentUser - Trusted Kişiler deposuna yüklenmiş hizmet sertifikalarını temizlediğinizden emin olun. Bunu yapmak için şu komutu kullanın: certmgr -del -r CurrentUser -s TrustedPeople -c -n <Fully Qualified Server Machine Name>
Örneğin: certmgr -del -r CurrentUser -s TrustedPeople -c -n server1.contoso.com
.