Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Destekleyici Belirteçler örneği, WS-Security kullanan bir iletiye nasıl ek belirteç ekleneceğini gösterir. Örnek, kullanıcı adı güvenlik belirtecine ek olarak bir X.509 ikili güvenlik belirteci ekler. Belirteç, istemciden hizmete WS-Security ileti üst bilgisine geçirilir ve iletinin bir bölümü, X.509 sertifikasının alıcıya sahip olduğunu kanıtlamak için X.509 güvenlik belirteciyle ilişkilendirilmiş özel anahtarla imzalanır. Bu, gönderenin kimliğini doğrulamak veya yetkilendirmek için bir iletiyle ilişkili birden çok talep olması gerektiğinde yararlıdır. Hizmet, istek-yanıt iletişim desenini tanımlayan bir sözleşme uygular.
Gösterir
Örnekte aşağıdakiler gösterilmiştir:
Bir istemci, ek güvenlik belirteçlerini bir hizmete nasıl iletebilir.
Sunucunun ek güvenlik belirteçleriyle ilişkili taleplere nasıl erişebileceği.
sunucunun X.509 sertifikasının ileti şifreleme ve imza için kullanılan simetrik anahtarı korumak için nasıl kullanıldığı.
Uyarı
Bu örnek için kurulum yordamı ve derleme yönergeleri bu konunun sonunda yer alır.
İstemci, Kullanıcı Adı Belirteci ve X.509 Destekleyici Güvenlik Belirteci ile Kimlik Doğrular.
Hizmet, BindingHelper ve EchoServiceHost sınıfları kullanılarak programlı bir şekilde oluşturulan tek bir uç noktayı iletişim için sunar. Uç nokta bir adres, bir bağlama ve bir sözleşmeden oluşur. Bağlama, SymmetricSecurityBindingElement ve HttpTransportBindingElement kullanılarak özel bir bağlama ile yapılandırılır. Bu örnek, iletim sırasında simetrik anahtarı korumak için bir hizmet X.509 sertifikasını kullanacak şekilde SymmetricSecurityBindingElement ayarlar ve UserNameToken'i destek X509SecurityToken ile birlikte WS-Security mesaj başlığına ekler. Simetrik anahtar, ileti gövdesini ve kullanıcı adı güvenlik belirtecini şifrelemek için kullanılır. Destek belirteci, WS-Security ileti üst bilgisinde ek bir ikili güvenlik belirteci olarak geçirilir. Destekleyici belirtecin orijinalliği, iletinin bir bölümü destekleyen X.509 güvenlik belirteciyle ilişkili özel anahtarla imzalanarak kanıtlanır.
public static Binding CreateMultiFactorAuthenticationBinding()
{
HttpTransportBindingElement httpTransport = new HttpTransportBindingElement();
// the message security binding element will be configured to require 2 tokens:
// 1) A username-password encrypted with the service token
// 2) A client certificate used to sign the message
// Instantiate a binding element that will require the username/password token in the message (encrypted with the server cert)
SymmetricSecurityBindingElement messageSecurity = SecurityBindingElement.CreateUserNameForCertificateBindingElement();
// Create supporting token parameters for the client X509 certificate.
X509SecurityTokenParameters clientX509SupportingTokenParameters = new X509SecurityTokenParameters();
// Specify that the supporting token is passed in message send by the client to the service
clientX509SupportingTokenParameters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
// Turn off derived keys
clientX509SupportingTokenParameters.RequireDerivedKeys = false;
// Augment the binding element to require the client's X509 certificate as an endorsing token in the message
messageSecurity.EndpointSupportingTokenParameters.Endorsing.Add(clientX509SupportingTokenParameters);
// Create a CustomBinding based on the constructed security binding element.
return new CustomBinding(messageSecurity, httpTransport);
}
Davranış, istemci kimlik doğrulaması için kullanılacak hizmet kimlik bilgilerini ve ayrıca hizmet X.509 sertifikası hakkındaki bilgileri belirtir. Örnek, X.509 sertifikasında konu adı olarak CN=localhost kullanır.
override protected void InitializeRuntime()
{
// Extract the ServiceCredentials behavior or create one.
ServiceCredentials serviceCredentials =
this.Description.Behaviors.Find<ServiceCredentials>();
if (serviceCredentials == null)
{
serviceCredentials = new ServiceCredentials();
this.Description.Behaviors.Add(serviceCredentials);
}
// Set the service certificate
serviceCredentials.ServiceCertificate.SetCertificate(
"CN=localhost");
/*
Setting the CertificateValidationMode to PeerOrChainTrust means that if the certificate is in the Trusted People store, then it will be 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.
*/
serviceCredentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust;
// Create the custom binding and add an endpoint to the service.
Binding multipleTokensBinding =
BindingHelper.CreateMultiFactorAuthenticationBinding();
this.AddServiceEndpoint(typeof(IEchoService),
multipleTokensBinding, string.Empty);
base.InitializeRuntime();
}
Hizmet kodu:
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class EchoService : IEchoService
{
public string Echo()
{
string userName;
string certificateSubjectName;
GetCallerIdentities(
OperationContext.Current.ServiceSecurityContext,
out userName,
out certificateSubjectName);
return $"Hello {userName}, {certificateSubjectName}";
}
public void Dispose()
{
}
bool TryGetClaimValue<TClaimResource>(ClaimSet claimSet,
string claimType, out TClaimResource resourceValue)
where TClaimResource : class
{
resourceValue = default(TClaimResource);
IEnumerable<Claim> matchingClaims =
claimSet.FindClaims(claimType, Rights.PossessProperty);
if(matchingClaims == null)
return false;
IEnumerator<Claim> enumerator = matchingClaims.GetEnumerator();
if (enumerator.MoveNext())
{
resourceValue =
(enumerator.Current.Resource == null) ? null :
(enumerator.Current.Resource as TClaimResource);
return true;
}
else
{
return false;
}
}
// Returns the username and certificate subject name provided by
//the client
void GetCallerIdentities(ServiceSecurityContext
callerSecurityContext,
out string userName, out string certificateSubjectName)
{
userName = null;
certificateSubjectName = null;
// Look in all the claimsets in the authorization context
foreach (ClaimSet claimSet in
callerSecurityContext.AuthorizationContext.ClaimSets)
{
if (claimSet is WindowsClaimSet)
{
// Try to find a Name claim. This will have been
// generated from the windows username.
string tmpName;
if (TryGetClaimValue<string>(claimSet, ClaimTypes.Name,
out tmpName))
{
userName = tmpName;
}
}
else if (claimSet is X509CertificateClaimSet)
{
// Try to find an X500DistinguishedName claim. This will
// have been generated from the client certificate.
X500DistinguishedName tmpDistinguishedName;
if (TryGetClaimValue<X500DistinguishedName>(claimSet,
ClaimTypes.X500DistinguishedName,
out tmpDistinguishedName))
{
certificateSubjectName = tmpDistinguishedName.Name;
}
}
}
}
}
İstemci uç noktası, hizmet uç noktasına benzer şekilde yapılandırılır. İstemci, bağlama oluşturmak için aynı BindingHelper sınıfı kullanır. Kurulumun geri kalanı sınıfında Client bulunur. İstemci, kullanıcı adı güvenlik belirteci, destekleyici X.509 güvenlik belirteci ve kurulum kodundaki hizmet X.509 sertifikası hakkındaki bilgileri istemci uç noktası davranışları koleksiyonuna ayarlar.
static void Main()
{
// Create the custom binding and an endpoint address for
// the service.
Binding multipleTokensBinding =
BindingHelper.CreateMultiFactorAuthenticationBinding();
EndpointAddress serviceAddress = new EndpointAddress(
"http://localhost/servicemodelsamples/service.svc");
ChannelFactory<IEchoService> channelFactory = null;
IEchoService client = null;
Console.WriteLine("Username authentication required.");
Console.WriteLine(
"Provide a valid machine or domain account. [domain\\user]");
Console.WriteLine(" Enter username:");
string username = Console.ReadLine();
Console.WriteLine(" Enter password:");
string password = "";
ConsoleKeyInfo info = Console.ReadKey(true);
while (info.Key != ConsoleKey.Enter)
{
if (info.Key != ConsoleKey.Backspace)
{
if (info.KeyChar != '\0')
{
password += info.KeyChar;
}
info = Console.ReadKey(true);
}
else if (info.Key == ConsoleKey.Backspace)
{
if (password != "")
{
password =
password.Substring(0, password.Length - 1);
}
info = Console.ReadKey(true);
}
}
for (int i = 0; i < password.Length; i++)
Console.Write("*");
Console.WriteLine();
try
{
// Create a proxy with the previously create binding and
// endpoint address
channelFactory =
new ChannelFactory<IEchoService>(
multipleTokensBinding, serviceAddress);
// configure the username credentials, the client
// certificate and the server certificate on the channel
// factory
channelFactory.Credentials.UserName.UserName = username;
channelFactory.Credentials.UserName.Password = password;
channelFactory.Credentials.ClientCertificate.SetCertificate(
"CN=client.com", StoreLocation.CurrentUser, StoreName.My);
channelFactory.Credentials.ServiceCertificate.SetDefaultCertificate(
"CN=localhost", StoreLocation.LocalMachine, StoreName.My);
client = channelFactory.CreateChannel();
Console.WriteLine("Echo service returned: {0}",
client.Echo());
((IChannel)client).Close();
channelFactory.Close();
}
catch (CommunicationException e)
{
Abort((IChannel)client, channelFactory);
// if there is a fault then print it out
FaultException fe = null;
Exception tmp = e;
while (tmp != null)
{
fe = tmp as FaultException;
if (fe != null)
{
break;
}
tmp = tmp.InnerException;
}
if (fe != null)
{
Console.WriteLine("The server sent back a fault: {0}",
fe.CreateMessageFault().Reason.GetMatchingTranslation().Text);
}
else
{
Console.WriteLine("The request failed with exception: {0}",e);
}
}
catch (TimeoutException)
{
Abort((IChannel)client, channelFactory);
Console.WriteLine("The request timed out");
}
catch (Exception e)
{
Abort((IChannel)client, channelFactory);
Console.WriteLine(
"The request failed with unexpected exception: {0}", e);
}
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
}
Arayanların Bilgilerini Görüntüleme
Çağıranın bilgilerini görüntülemek için aşağıdaki kodda gösterildiği gibi öğesini kullanabilirsiniz ServiceSecurityContext.Current.AuthorizationContext.ClaimSets . geçerli ServiceSecurityContext.Current.AuthorizationContext.ClaimSets çağıranla ilişkili yetkilendirme taleplerini içerir. Bu talepler, iletide alınan her belirteç için Windows Communication Foundation (WCF) tarafından otomatik olarak sağlanır.
bool TryGetClaimValue<TClaimResource>(ClaimSet claimSet, string
claimType, out TClaimResource resourceValue)
where TClaimResource : class
{
resourceValue = default(TClaimResource);
IEnumerable<Claim> matchingClaims =
claimSet.FindClaims(claimType, Rights.PossessProperty);
if (matchingClaims == null)
return false;
IEnumerator<Claim> enumerator = matchingClaims.GetEnumerator();
if (enumerator.MoveNext())
{
resourceValue = (enumerator.Current.Resource == null) ? null : (enumerator.Current.Resource as TClaimResource);
return true;
}
else
{
return false;
}
}
// Returns the username and certificate subject name provided by the client
void GetCallerIdentities(ServiceSecurityContext callerSecurityContext, out string userName, out string certificateSubjectName)
{
userName = null;
certificateSubjectName = null;
// Look in all the claimsets in the authorization context
foreach (ClaimSet claimSet in
callerSecurityContext.AuthorizationContext.ClaimSets)
{
if (claimSet is WindowsClaimSet)
{
// Try to find a Name claim. This will have been generated
//from the windows username.
string tmpName;
if (TryGetClaimValue<string>(claimSet, ClaimTypes.Name,
out tmpName))
{
userName = tmpName;
}
}
else if (claimSet is X509CertificateClaimSet)
{
//Try to find an X500DistinguishedName claim.
//This will have been generated from the client
//certificate.
X500DistinguishedName tmpDistinguishedName;
if (TryGetClaimValue<X500DistinguishedName>(claimSet,
ClaimTypes.X500DistinguishedName,
out tmpDistinguishedName))
{
certificateSubjectName = tmpDistinguishedName.Name;
}
}
}
}
Örneği Çalıştır
Örneği çalıştırdığınızda, istemci ilk olarak kullanıcı adı belirteci için kullanıcı adı ve parola girmenizi ister. Hizmetteki WCF, kullanıcı adı belirtecinde sağlanan değerleri sistem tarafından sağlanan kimlikle eşlediğinden, sistem hesabınız için doğru değerleri sağladığınızdan emin olun. Bundan sonra, istemci hizmetten gelen yanıtı görüntüler. İstemciyi kapatmak için istemci penceresinde ENTER tuşuna basın.
Batch Dosyasını Ayarlama
Bu örneğe dahil Setup.bat toplu iş dosyası, sunucuyu ilgili sertifikalarla yapılandırarak sunucu sertifika tabanlı güvenlik gerektiren Internet Information Services (IIS) barındırılan uygulamasını çalıştırmanıza olanak tanır. Bu toplu iş dosyası, farklı makinelerde çalışacak veya barındırılmayan bir durumda çalışması için değiştirilmelidir.
Aşağıda, toplu iş dosyalarının farklı bölümlerine kısa bir genel bakış sağlanmaktadır, böylece bunlar uygun yapılandırmada çalışacak şekilde değiştirilebilir.
İstemci Sertifikası Oluşturma
Setup.bat toplu iş dosyasındaki aşağıdaki satırlar kullanılacak istemci sertifikasını oluşturur. değişkeni, %CLIENT_NAME% istemci sertifikasının konusunu belirtir. Bu örnek konu adı olarak "client.com" kullanır.
Sertifika, CurrentUser mağaza konumu altındaki Kişisel (Kişisel) mağazada saklanır.
echo ************
echo making client cert
echo ************
makecert.exe -sr CurrentUser -ss MY -a sha1 -n CN=%CLIENT_NAME% -sky exchange -pe
İstemci Sertifikasını Sunucunun Güvenilen Deposuna Yükleme
Setup.bat toplu iş dosyasındaki aşağıdaki satır, istemci sertifikasını sunucunun güvenilen kişiler deposuna kopyalar. Makecert.exe tarafından oluşturulan sertifikalara sunucunun 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.
echo ************
echo copying client cert to server's CurrentUserstore
echo ************
certmgr.exe -add -r CurrentUser -s My -c -n %CLIENT_NAME% -r LocalMachine -s TrustedPeople
Sunucu Sertifikası Oluşturma
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. Bu toplu iş dosyasında varsayılan değer localhost'tır.
Sertifika, LocalMachine depolama konumu altında My (Personal) deposunda depolanır. Sertifika, IIS tarafından barındırılan hizmetler için LocalMachine deposunda depolanır. Kendinden barındırmalı hizmetler için, LocalMachine dizesini CurrentUser ile değiştirerek sunucu sertifikasını CurrentUser mağaza konumunda saklamak amacıyla toplu iş dosyasını değiştirmeniz gerekir.
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
İstemcinin Güvenilen Sertifika Deposuna Sunucu Sertifikası 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.
echo ************
echo copying server cert to client's TrustedPeople store
echo ************certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
Sertifikanın Özel Anahtarına Erişimi Etkinleştirme
IIS tarafından barındırılan hizmetten sertifika özel anahtarına erişimi etkinleştirmek için, IIS tarafından barındırılan işlemin çalıştığı kullanıcı hesabına özel anahtar için uygun izinler verilmelidir. Bu, Setup.bat betiğindeki son adımlarla gerçekleştirilir.
echo ************
echo setting privileges on server certificates
echo ************
for /F "delims=" %%i in ('"%ProgramFiles%\ServiceModelSampleTools\FindPrivateKey.exe" My LocalMachine -n CN^=%SERVER_NAME% -a') do set PRIVATE_KEY_FILE=%%i
set WP_ACCOUNT=NT AUTHORITY\NETWORK SERVICE
(ver | findstr /C:"5.1") && set WP_ACCOUNT=%COMPUTERNAME%\ASPNET
echo Y|cacls.exe "%PRIVATE_KEY_FILE%" /E /G "%WP_ACCOUNT%":R
iisreset
Örneği ayarlamak, derlemek ve çalıştırmak için
Windows Communication Foundation Örnekleri içinOne-Time Kurulum Yordamı'nı gerçekleştirdiğinizden emin olun.
Çözümü oluşturmak için Windows Communication Foundation Örnekleri Oluşturma başlığındaki yönergeleri izleyin.
Örneği tek veya makineler arası bir yapılandırmada çalıştırmak için aşağıdaki yönergeleri kullanın.
Örneği aynı makinede çalıştırmak için
Visual Studio komut istemi içindeki örnek yükleme klasöründen Setup.bat yönetici ayrıcalıklarıyla çalıştırın. Bu, örneği çalıştırmak için gereken tüm sertifikaları yükler.
Uyarı
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 dizini işaret eder. Örnekle işiniz bittiğinde Cleanup.bat çalıştırarak sertifikaları kaldırdığınızdan emin olun. Diğer güvenlik örnekleri aynı sertifikaları kullanır.
\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ı.
Örnek kodu makineler arasında çalıştırmak için
Hizmet makinesinde bir dizin oluşturun. Internet Information Services (IIS) yönetim aracını kullanarak bu dizin için servicemodelsamples adlı bir sanal uygulama oluşturun.
\inetpub\wwwroot\servicemodelsamples konumundaki hizmet programı dosyalarını hizmet makinesindeki sanal dizine kopyalayın. \bin alt dizinindeki dosyaları kopyaladığınızdan emin olun. Ayrıca Setup.bat, Cleanup.batve ImportClientCert.bat dosyalarını hizmet makinesine kopyalayın.
İstemci ikili dosyaları için istemci makinesinde bir dizin oluşturun.
İstemci programı dosyalarını istemci makinesindeki istemci dizinine kopyalayın. Ayrıca, Setup.bat, Cleanup.batve 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şkeniylesetup.batçalıştırmakservice, makinenin tam etki alanı adına sahip bir hizmet sertifikası oluşturur ve hizmet sertifikasını Service.cer adlı bir dosyaya aktarır.Web.config'ı, makinenin tam etki alanı adıyla aynı olan yeni sertifika adını yansıtacak şekilde (
findValue, <serviceCertificate> özniteliğinde) düzenleyin.Service.cer dosyasını hizmet dizininden istemci makinesindeki istemci dizinine kopyalayın.
İstemcide, yönetici ayrıcalıklarıyla açılan Visual Studio için Geliştirici Komut İstemi'nde
setup.bat clientkomutunu çalıştırın.setup.bat'ıclientbağımsız değişkeniyle çalıştırmak, client.com adlı bir istemci sertifikası oluşturarak sertifikayı Client.cer adlı bir dosyaya aktarır.İstemci makinesindeki 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'u sunucunun tam etki alanı adıyla değiştirin.
Client.cer dosyasını istemci dizininden sunucudaki hizmet dizinine kopyalayın.
İstemcide ImportServiceCert.batçalıştırın. Bu, hizmet sertifikasını Service.cer dosyasından CurrentUser - TrustedPeople deposuna aktarır.
sunucusunda ImportClientCert.batkomutunu çalıştırın. Bu, istemci sertifikasını Client.cer dosyasından LocalMachine - TrustedPeople deposuna aktarır.
İstemci makinesinde 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 temizlik yapmak için
- Örneği çalıştırmayı bitirdikten sonra örnekler klasöründe Cleanup.bat çalıştırın.
Uyarı
Bu betik, bu örneği makineler arasında çalıştırırken istemcideki hizmet sertifikalarını kaldırmaz. Makineler arasında sertifika kullanan WCF örnekleri çalıştırdıysanız CurrentUser - TrustedPeople deposunda yüklü olan 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.