Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Sampel ini menunjukkan cara menambahkan implementasi token kustom ke dalam aplikasi Windows Communication Foundation (WCF). Contohnya menggunakan CreditCardToken untuk meneruskan informasi dengan aman tentang kartu kredit klien ke layanan. Token diteruskan di header pesan WS-Security serta ditandatangani dan dienkripsi menggunakan elemen pengikatan keamanan simetris beserta isi pesan dan header pesan lainnya. Ini berguna dalam kasus di mana token bawaan tidak cukup. Sampel ini menunjukkan cara memberikan token keamanan kustom ke layanan alih-alih menggunakan salah satu token bawaan. Layanan ini menerapkan kontrak yang mendefinisikan pola komunikasi balasan permintaan.
Nota
Prosedur penyiapan dan instruksi build untuk sampel ini terletak di akhir topik ini.
Untuk meringkas, sampel ini menunjukkan hal berikut:
Bagaimana klien dapat meneruskan token keamanan kustom ke layanan.
Bagaimana layanan dapat menggunakan dan memvalidasi token keamanan kustom.
Bagaimana kode layanan WCF dapat memperoleh informasi tentang token keamanan yang diterima termasuk token keamanan kustom.
Bagaimana sertifikat X.509 server digunakan untuk melindungi kunci simetris yang digunakan untuk enkripsi pesan dan tanda tangan.
Autentikasi Klien Menggunakan Token Keamanan Kustom
Layanan ini mengekspos satu titik akhir yang secara terprogram dibuat menggunakan kelas BindingHelper dan EchoServiceHost. Titik akhir terdiri dari alamat, pengikatan, dan kontrak. Pengikatan dikonfigurasi dengan pengikatan kustom menggunakan SymmetricSecurityBindingElement dan HttpTransportBindingElement. Sampel ini mengatur SymmetricSecurityBindingElement untuk menggunakan sertifikat X.509 dari sebuah layanan guna melindungi kunci simetris selama transmisi dan untuk meneruskan CreditCardToken kustom di header pesan WS-Security sebagai token keamanan yang telah ditandatangani dan dienkripsi. Perilaku menentukan kredensial layanan yang akan digunakan untuk autentikasi klien dan juga informasi tentang sertifikat X.509 layanan.
public static class BindingHelper
{
public static Binding CreateCreditCardBinding()
{
var httpTransport = new HttpTransportBindingElement();
// The message security binding element will be configured to require a credit card.
// The token that is encrypted with the service's certificate.
var messageSecurity = new SymmetricSecurityBindingElement();
messageSecurity.EndpointSupportingTokenParameters.SignedEncrypted.Add(new CreditCardTokenParameters());
X509SecurityTokenParameters x509ProtectionParameters = new X509SecurityTokenParameters();
x509ProtectionParameters.InclusionMode = SecurityTokenInclusionMode.Never;
messageSecurity.ProtectionTokenParameters = x509ProtectionParameters;
return new CustomBinding(messageSecurity, httpTransport);
}
}
Untuk menggunakan token kartu kredit dalam pesan, sampel menggunakan kredensial layanan kustom untuk menyediakan fungsionalitas ini. Kelas kredensial layanan terletak di CreditCardServiceCredentials kelas dan ditambahkan ke kumpulan perilaku host layanan dalam EchoServiceHost.InitializeRuntime metode .
class EchoServiceHost : ServiceHost
{
string creditCardFile;
public EchoServiceHost(parameters Uri[] addresses)
: base(typeof(EchoService), addresses)
{
creditCardFile = ConfigurationManager.AppSettings["creditCardFile"];
if (string.IsNullOrEmpty(creditCardFile))
{
throw new ConfigurationErrorsException("creditCardFile not specified in service config");
}
creditCardFile = String.Format("{0}\\{1}", System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath, creditCardFile);
}
override protected void InitializeRuntime()
{
// Create a credit card service credentials and add it to the behaviors.
CreditCardServiceCredentials serviceCredentials = new CreditCardServiceCredentials(this.creditCardFile);
serviceCredentials.ServiceCertificate.SetCertificate("CN=localhost", StoreLocation.LocalMachine, StoreName.My);
this.Description.Behaviors.Remove((typeof(ServiceCredentials)));
this.Description.Behaviors.Add(serviceCredentials);
// Register a credit card binding for the endpoint.
Binding creditCardBinding = BindingHelper.CreateCreditCardBinding();
this.AddServiceEndpoint(typeof(IEchoService), creditCardBinding, string.Empty);
base.InitializeRuntime();
}
}
Titik akhir klien dikonfigurasi dengan cara yang sama seperti titik akhir layanan. Klien menggunakan kelas yang sama BindingHelper untuk membuat pengikatan. Sisa konfigurasi terletak di Client Kelas. Klien juga menetapkan informasi yang harus dimasukkan ke dalam CreditCardToken dan informasi tentang sertifikat layanan X.509 dalam kode penyiapan dengan menambahkan sebuah instance dengan data yang tepat ke koleksi perilaku endpoint klien. Sampel menggunakan sertifikat X.509, dengan nama subjek ditetapkan ke CN=localhost sebagai sertifikat layanan.
Binding creditCardBinding = BindingHelper.CreateCreditCardBinding();
var serviceAddress = new EndpointAddress("http://localhost/servicemodelsamples/service.svc");
// Create a client with given client endpoint configuration.
channelFactory = new ChannelFactory<IEchoService>(creditCardBinding, serviceAddress);
// Configure the credit card credentials on the channel factory.
var credentials =
new CreditCardClientCredentials(
new CreditCardInfo(creditCardNumber, issuer, expirationTime));
// Configure the service certificate on the credentials.
credentials.ServiceCertificate.SetDefaultCertificate(
"CN=localhost", StoreLocation.LocalMachine, StoreName.My);
// Replace ClientCredentials with CreditCardClientCredentials.
channelFactory.Endpoint.Behaviors.Remove(typeof(ClientCredentials));
channelFactory.Endpoint.Behaviors.Add(credentials);
client = channelFactory.CreateChannel();
Console.WriteLine($"Echo service returned: {client.Echo()}");
((IChannel)client).Close();
channelFactory.Close();
Implementasi Token Keamanan Kustom
Untuk mengaktifkan token keamanan kustom di WCF, buat representasi objek dari token keamanan kustom. Sampel memiliki representasi ini dalam kelas CreditCardToken tersebut. Representasi objek bertanggung jawab untuk menyimpan semua informasi token keamanan yang relevan dan untuk memberikan daftar kunci keamanan yang terkandung dalam token keamanan. Dalam hal ini, token keamanan kartu kredit tidak berisi kunci keamanan apa pun.
Bagian berikutnya menjelaskan apa yang harus dilakukan untuk mengaktifkan token kustom yang akan ditransmisikan melalui kawat dan dikonsumsi oleh titik akhir WCF.
class CreditCardToken : SecurityToken
{
CreditCardInfo cardInfo;
DateTime effectiveTime = DateTime.UtcNow;
string id;
ReadOnlyCollection<SecurityKey> securityKeys;
public CreditCardToken(CreditCardInfo cardInfo) : this(cardInfo, Guid.NewGuid().ToString()) { }
public CreditCardToken(CreditCardInfo cardInfo, string id)
{
if (cardInfo == null)
throw new ArgumentNullException(nameof(cardInfo));
if (id == null)
throw new ArgumentNullException(nameof(id));
this.cardInfo = cardInfo;
this.id = id;
// The credit card token is not capable of any cryptography.
this.securityKeys = new ReadOnlyCollection<SecurityKey>(new List<SecurityKey>());
}
public CreditCardInfo CardInfo { get { return this.cardInfo; } }
public override ReadOnlyCollection<SecurityKey> SecurityKeys { get { return this.securityKeys; } }
public override DateTime ValidFrom { get { return this.effectiveTime; } }
public override DateTime ValidTo { get { return this.cardInfo.ExpirationDate; } }
public override string Id { get { return this.id; } }
}
Mendapatkan Token Kartu Kredit Kustom ke dan dari Pesan
Serializer token keamanan di WCF bertanggung jawab untuk membuat representasi objek token keamanan dari XML dalam pesan dan membuat bentuk XML dari token keamanan. Mereka juga bertanggung jawab atas fungsionalitas lain seperti membaca dan menulis pengidentifikasi kunci yang menunjuk ke token keamanan, tetapi contoh ini hanya menggunakan fungsionalitas terkait token keamanan. Untuk mengaktifkan token kustom, Anda harus menerapkan serializer token keamanan Anda sendiri. Sampel ini menggunakan CreditCardSecurityTokenSerializer kelas untuk tujuan ini.
Pada layanan, serializer kustom membaca formulir XML dari token kustom dan membuat representasi objek token kustom darinya.
Pada klien, CreditCardSecurityTokenSerializer kelas menulis informasi yang terkandung dalam representasi objek token keamanan ke dalam penulis XML.
public class CreditCardSecurityTokenSerializer : WSSecurityTokenSerializer
{
public CreditCardSecurityTokenSerializer(SecurityTokenVersion version) : base() { }
protected override bool CanReadTokenCore(XmlReader reader)
{
XmlDictionaryReader localReader = XmlDictionaryReader.CreateDictionaryReader(reader);
if (reader == null)
throw new ArgumentNullException(nameof(reader));
if (reader.IsStartElement(Constants.CreditCardTokenName, Constants.CreditCardTokenNamespace))
return true;
return base.CanReadTokenCore(reader);
}
protected override SecurityToken ReadTokenCore(XmlReader reader, SecurityTokenResolver tokenResolver)
{
if (reader == null)
throw new ArgumentNullException(nameof(reader));
if (reader.IsStartElement(Constants.CreditCardTokenName, Constants.CreditCardTokenNamespace))
{
string id = reader.GetAttribute(Constants.Id, Constants.WsUtilityNamespace);
reader.ReadStartElement();
// Read the credit card number.
string creditCardNumber = reader.ReadElementString(Constants.CreditCardNumberElementName, Constants.CreditCardTokenNamespace);
// Read the expiration date.
string expirationTimeString = reader.ReadElementString(Constants.CreditCardExpirationElementName, Constants.CreditCardTokenNamespace);
DateTime expirationTime = XmlConvert.ToDateTime(expirationTimeString, XmlDateTimeSerializationMode.Utc);
// Read the issuer of the credit card.
string creditCardIssuer = reader.ReadElementString(Constants.CreditCardIssuerElementName, Constants.CreditCardTokenNamespace);
reader.ReadEndElement();
var cardInfo = new CreditCardInfo(creditCardNumber, creditCardIssuer, expirationTime);
return new CreditCardToken(cardInfo, id);
}
else
{
return WSSecurityTokenSerializer.DefaultInstance.ReadToken(reader, tokenResolver);
}
}
protected override bool CanWriteTokenCore(SecurityToken token)
{
if (token is CreditCardToken)
return true;
return base.CanWriteTokenCore(token);
}
protected override void WriteTokenCore(XmlWriter writer, SecurityToken token)
{
if (writer == null)
throw new ArgumentNullException(nameof(writer));
if (token == null)
throw new ArgumentNullException(nameof(token));
CreditCardToken c = token as CreditCardToken;
if (c != null)
{
writer.WriteStartElement(Constants.CreditCardTokenPrefix, Constants.CreditCardTokenName, Constants.CreditCardTokenNamespace);
writer.WriteAttributeString(Constants.WsUtilityPrefix, Constants.Id, Constants.WsUtilityNamespace, token.Id);
writer.WriteElementString(Constants.CreditCardNumberElementName, Constants.CreditCardTokenNamespace, c.CardInfo.CardNumber);
writer.WriteElementString(Constants.CreditCardExpirationElementName, Constants.CreditCardTokenNamespace, XmlConvert.ToString(c.CardInfo.ExpirationDate, XmlDateTimeSerializationMode.Utc));
writer.WriteElementString(Constants.CreditCardIssuerElementName, Constants.CreditCardTokenNamespace, c.CardInfo.CardIssuer);
writer.WriteEndElement();
writer.Flush();
}
else
{
base.WriteTokenCore(writer, token);
}
}
}
Cara Membuat Kelas Penyedia Token dan Autentikator Token
Kredensial klien dan layanan bertanggung jawab untuk menyediakan instans manajer token keamanan. Instans manajer token keamanan digunakan untuk mendapatkan penyedia token, pengautentikasi token, dan penyeri token.
Penyedia token membuat representasi objek dari token berdasarkan informasi yang terkandung dalam kredensial klien atau layanan. Representasi objek token kemudian ditulis ke pesan menggunakan serializer token (dibahas di bagian sebelumnya).
Pengautentikasi token memvalidasi token yang tiba dalam pesan. Representasi objek untuk token yang masuk dibuat oleh serializer token. Representasi objek ini kemudian diteruskan ke pengautentikasi token untuk validasi. Setelah token berhasil divalidasi, pengautentikasi token mengembalikan kumpulan IAuthorizationPolicy objek yang mewakili informasi yang terkandung dalam token. Informasi ini digunakan nanti selama pemrosesan pesan untuk melakukan keputusan otorisasi dan memberikan klaim untuk aplikasi. Dalam contoh ini, pengautentikasi token kartu kredit menggunakan CreditCardTokenAuthorizationPolicy untuk tujuan ini.
Serializer token bertanggung jawab untuk menghasilkan representasi objek dari token ke dan dari saluran komunikasi. Ini dibahas di bagian sebelumnya.
Dalam sampel ini, kami menggunakan penyedia token hanya pada klien dan pengautentikasi token hanya pada layanan, karena kami ingin mengirimkan token kartu kredit hanya dalam arah klien-ke-layanan.
Fungsionalitas pada klien terletak di CreditCardClientCredentialskelas , CreditCardClientCredentialsSecurityTokenManager dan CreditCardTokenProvider .
Pada layanan, fungsionalitas berada di kelas CreditCardServiceCredentials, CreditCardServiceCredentialsSecurityTokenManager, CreditCardTokenAuthenticator, dan CreditCardTokenAuthorizationPolicy.
public class CreditCardClientCredentials : ClientCredentials
{
CreditCardInfo creditCardInfo;
public CreditCardClientCredentials(CreditCardInfo creditCardInfo)
: base()
{
if (creditCardInfo == null)
throw new ArgumentNullException(nameof(creditCardInfo));
this.creditCardInfo = creditCardInfo;
}
public CreditCardInfo CreditCardInfo
{
get { return this.creditCardInfo; }
}
protected override ClientCredentials CloneCore()
{
return new CreditCardClientCredentials(this.creditCardInfo);
}
public override SecurityTokenManager CreateSecurityTokenManager()
{
return new CreditCardClientCredentialsSecurityTokenManager(this);
}
}
public class CreditCardClientCredentialsSecurityTokenManager : ClientCredentialsSecurityTokenManager
{
CreditCardClientCredentials creditCardClientCredentials;
public CreditCardClientCredentialsSecurityTokenManager(CreditCardClientCredentials creditCardClientCredentials)
: base (creditCardClientCredentials)
{
this.creditCardClientCredentials = creditCardClientCredentials;
}
public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
{
// Handle this token for Custom.
if (tokenRequirement.TokenType == Constants.CreditCardTokenType)
return new CreditCardTokenProvider(this.creditCardClientCredentials.CreditCardInfo);
// Return server cert.
else if (tokenRequirement is InitiatorServiceModelSecurityTokenRequirement)
{
if (tokenRequirement.TokenType == SecurityTokenTypes.X509Certificate)
{
return new X509SecurityTokenProvider(creditCardClientCredentials.ServiceCertificate.DefaultCertificate);
}
}
return base.CreateSecurityTokenProvider(tokenRequirement);
}
public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version)
{
return new CreditCardSecurityTokenSerializer(version);
}
}
class CreditCardTokenProvider : SecurityTokenProvider
{
CreditCardInfo creditCardInfo;
public CreditCardTokenProvider(CreditCardInfo creditCardInfo) : base()
{
if (creditCardInfo == null)
throw new ArgumentNullException(nameof(creditCardInfo));
this.creditCardInfo = creditCardInfo;
}
protected override SecurityToken GetTokenCore(TimeSpan timeout)
{
SecurityToken result = new CreditCardToken(this.creditCardInfo);
return result;
}
}
public class CreditCardServiceCredentials : ServiceCredentials
{
string creditCardFile;
public CreditCardServiceCredentials(string creditCardFile)
: base()
{
if (creditCardFile == null)
throw new ArgumentNullException(nameof(creditCardFile));
this.creditCardFile = creditCardFile;
}
public string CreditCardDataFile
{
get { return this.creditCardFile; }
}
protected override ServiceCredentials CloneCore()
{
return new CreditCardServiceCredentials(this.creditCardFile);
}
public override SecurityTokenManager CreateSecurityTokenManager()
{
return new CreditCardServiceCredentialsSecurityTokenManager(this);
}
}
public class CreditCardServiceCredentialsSecurityTokenManager : ServiceCredentialsSecurityTokenManager
{
CreditCardServiceCredentials creditCardServiceCredentials;
public CreditCardServiceCredentialsSecurityTokenManager(CreditCardServiceCredentials creditCardServiceCredentials)
: base(creditCardServiceCredentials)
{
this.creditCardServiceCredentials = creditCardServiceCredentials;
}
public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver)
{
if (tokenRequirement.TokenType == Constants.CreditCardTokenType)
{
outOfBandTokenResolver = null;
return new CreditCardTokenAuthenticator(creditCardServiceCredentials.CreditCardDataFile);
}
return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver);
}
public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version)
{
return new CreditCardSecurityTokenSerializer(version);
}
}
class CreditCardTokenAuthenticator : SecurityTokenAuthenticator
{
string creditCardsFile;
public CreditCardTokenAuthenticator(string creditCardsFile)
{
this.creditCardsFile = creditCardsFile;
}
protected override bool CanValidateTokenCore(SecurityToken token)
{
return (token is CreditCardToken);
}
protected override ReadOnlyCollection<IAuthorizationPolicy> ValidateTokenCore(SecurityToken token)
{
CreditCardToken creditCardToken = token as CreditCardToken;
if (creditCardToken.CardInfo.ExpirationDate < DateTime.UtcNow)
throw new SecurityTokenValidationException("The credit card has expired.");
if (!IsCardNumberAndExpirationValid(creditCardToken.CardInfo))
throw new SecurityTokenValidationException("Unknown or invalid credit card.");
// the credit card token has only 1 claim - the card number. The issuer for the claim is the
// credit card issuer
var cardIssuerClaimSet = new DefaultClaimSet(new Claim(ClaimTypes.Name, creditCardToken.CardInfo.CardIssuer, Rights.PossessProperty));
var cardClaimSet = new DefaultClaimSet(cardIssuerClaimSet, new Claim(Constants.CreditCardNumberClaim, creditCardToken.CardInfo.CardNumber, Rights.PossessProperty));
var policies = new List<IAuthorizationPolicy>(1);
policies.Add(new CreditCardTokenAuthorizationPolicy(cardClaimSet));
return policies.AsReadOnly();
}
/// <summary>
/// Helper method to check if a given credit card entry is present in the User DB
/// </summary>
private bool IsCardNumberAndExpirationValid(CreditCardInfo cardInfo)
{
try
{
using (var myStreamReader = new StreamReader(this.creditCardsFile))
{
string line = "";
while ((line = myStreamReader.ReadLine()) != null)
{
string[] splitEntry = line.Split('#');
if (splitEntry[0] == cardInfo.CardNumber)
{
string expirationDateString = splitEntry[1].Trim();
DateTime expirationDateOnFile = DateTime.Parse(expirationDateString, System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.AdjustToUniversal);
if (cardInfo.ExpirationDate == expirationDateOnFile)
{
string issuer = splitEntry[2];
return issuer.Equals(cardInfo.CardIssuer, StringComparison.InvariantCultureIgnoreCase);
}
else
{
return false;
}
}
}
return false;
}
}
catch (Exception e)
{
throw new Exception("BookStoreService: Error while retrieving credit card information from User DB " + e.ToString());
}
}
}
public class CreditCardTokenAuthorizationPolicy : IAuthorizationPolicy
{
string id;
ClaimSet issuer;
IEnumerable<ClaimSet> issuedClaimSets;
public CreditCardTokenAuthorizationPolicy(ClaimSet issuedClaims)
{
if (issuedClaims == null)
throw new ArgumentNullException(nameof(issuedClaims));
this.issuer = issuedClaims.Issuer;
this.issuedClaimSets = new ClaimSet[] { issuedClaims };
this.id = Guid.NewGuid().ToString();
}
public ClaimSet Issuer { get { return this.issuer; } }
public string Id { get { return this.id; } }
public bool Evaluate(EvaluationContext context, ref object state)
{
foreach (ClaimSet issuance in this.issuedClaimSets)
{
context.AddClaimSet(this, issuance);
}
return true;
}
}
Menampilkan Informasi Penelepon
Untuk menampilkan informasi pemanggil, gunakan seperti yang ServiceSecurityContext.Current.AuthorizationContext.ClaimSets ditunjukkan dalam kode sampel berikut.
ServiceSecurityContext.Current.AuthorizationContext.ClaimSets berisi klaim otorisasi yang terkait dengan pemanggil saat ini. Klaim disediakan oleh CreditCardToken kelas dalam koleksinya AuthorizationPolicies .
bool TryGetStringClaimValue(ClaimSet claimSet, string claimType, out string claimValue)
{
claimValue = null;
IEnumerable<Claim> matchingClaims = claimSet.FindClaims(claimType, Rights.PossessProperty);
if (matchingClaims == null)
return false;
IEnumerator<Claim> enumerator = matchingClaims.GetEnumerator();
enumerator.MoveNext();
claimValue = (enumerator.Current.Resource == null) ? null :
enumerator.Current.Resource.ToString();
return true;
}
string GetCallerCreditCardNumber()
{
foreach (ClaimSet claimSet in
ServiceSecurityContext.Current.AuthorizationContext.ClaimSets)
{
string creditCardNumber = null;
if (TryGetStringClaimValue(claimSet,
Constants.CreditCardNumberClaim, out creditCardNumber))
{
string issuer;
if (!TryGetStringClaimValue(claimSet.Issuer,
ClaimTypes.Name, out issuer))
{
issuer = "Unknown";
}
return $"Credit card '{creditCardNumber}' issued by '{issuer}'";
}
}
return "Credit card is not known";
}
Saat Anda menjalankan sampel, permintaan dan respons operasi ditampilkan di jendela konsol klien. Tekan ENTER di jendela klien untuk mematikan klien.
Menyiapkan File Batch
File batch Setup.bat yang disertakan dengan sampel ini memungkinkan Anda mengonfigurasi server dengan sertifikat yang relevan untuk menjalankan aplikasi yang dihosting IIS yang memerlukan keamanan berbasis sertifikat server. File batch ini harus dimodifikasi agar berfungsi di berbagai komputer atau tanpa host.
Berikut ini memberikan gambaran singkat tentang berbagai bagian file batch sehingga dapat dimodifikasi untuk dijalankan dalam konfigurasi yang sesuai.
Membuat sertifikat server:
Baris berikut dari
Setup.batfile batch membuat sertifikat server yang akan digunakan. Variabel%SERVER_NAME%menentukan nama server. Ubah variabel ini untuk menentukan nama server Anda sendiri. Default dalam file batch ini adalah localhost. Jika Anda mengubah%SERVER_NAME%variabel, Anda harus melalui file Client.cs dan Service.cs dan mengganti semua instans localhost dengan nama server yang Anda gunakan dalam skrip Setup.bat.Sertifikat disimpan di penyimpanan Pribadi pada lokasi penyimpanan
LocalMachine. Sertifikat disimpan di penyimpanan LocalMachine untuk layanan yang dihosting IIS. Untuk layanan yang dihost sendiri, Anda harus memodifikasi file batch untuk menyimpan sertifikat klien di lokasi penyimpanan CurrentUser dengan mengganti string LocalMachine dengan CurrentUser.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 -peMenginstal sertifikat server ke penyimpanan sertifikat tepercaya klien:
Baris-baris berikut dalam file batch Setup.bat menyalin sertifikat server ke penyimpanan tepercaya klien. Langkah ini diperlukan karena sertifikat yang dihasilkan oleh Makecert.exe tidak dipercaya secara implisit oleh sistem klien. Jika Anda sudah memiliki sertifikat yang berakar pada sertifikat akar tepercaya klien—misalnya, sertifikat yang dikeluarkan Microsoft—langkah mengisi penyimpanan sertifikat klien dengan sertifikat server tidak diperlukan.
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 TrustedPeopleUntuk mengaktifkan akses ke kunci privat sertifikat dari layanan yang dihosting IIS, akun pengguna tempat proses yang dihosting IIS berjalan harus diberikan izin yang sesuai untuk kunci privat. Ini dicapai dengan langkah-langkah terakhir dalam skrip Setup.bat.
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
Nota
File batch Setup.bat dirancang untuk dijalankan dari Visual Studio Command Prompt. Variabel lingkungan PATH yang diatur dalam Prompt Perintah Visual Studio menunjuk ke direktori yang berisi executable yang diperlukan oleh skrip Setup.bat.
Untuk menyiapkan dan membangun sampel
Pastikan Anda telah melakukan Prosedur Penyiapan One-Time untuk Sampel Windows Communication Foundation.
Untuk membangun solusi, ikuti instruksi dalam Membangun Sampel Windows Communication Foundation.
Untuk menjalankan sampel pada komputer yang sama
- Buka jendela Prompt Perintah Visual Studio dengan hak istimewa administrator dan jalankan Setup.bat dari folder instalasi sampel. Ini menginstal semua sertifikat yang diperlukan untuk menjalankan sampel. Pastikan jalur menyertakan folder tempat Makecert.exe berada.
Nota
Pastikan untuk menghapus sertifikat dengan menjalankan Cleanup.bat setelah selesai dengan sampel. Sampel keamanan lainnya menggunakan sertifikat yang sama.
Luncurkan Client.exe dari direktori client\bin. Aktivitas klien ditampilkan pada aplikasi konsol klien.
Jika klien dan layanan tidak dapat berkomunikasi, lihat Tips Pemecahan Masalah untuk Sampel WCF.
Untuk menjalankan sampel di beberapa komputer
Buat direktori di komputer layanan untuk biner layanan.
Salin file program layanan ke direktori layanan pada komputer layanan. Jangan lupa untuk menyalin CreditCardFile.txt; jika tidak, pengautentikasi kartu kredit tidak dapat memvalidasi informasi kartu kredit yang dikirim dari klien. Salin juga file Setup.bat dan Cleanup.bat ke komputer layanan.
Anda harus memiliki sertifikat server dengan nama subjek yang berisi nama domain komputer yang sepenuhnya memenuhi syarat. Anda dapat membuatnya menggunakan Setup.bat jika Anda mengubah variabel
%SERVER_NAME%menjadi nama lengkap komputer yang memenuhi syarat di mana layanan di-host. Perhatikan bahwa file Setup.bat harus dijalankan di Prompt Perintah Pengembang untuk Visual Studio yang dibuka dengan hak istimewa administrator.Salin sertifikat server ke penyimpanan CurrentUser-TrustedPeople pada klien. Anda harus melakukan ini hanya jika sertifikat server tidak dikeluarkan oleh penerbit tepercaya.
Dalam file EchoServiceHost.cs, ubah nilai nama subjek sertifikat untuk menentukan nama komputer yang sepenuhnya memenuhi syarat alih-alih localhost.
Salin file program klien dari folder \client\bin\, di bawah folder khusus bahasa, ke komputer klien.
Dalam file Client.cs, ubah nilai alamat titik akhir agar sesuai dengan alamat baru layanan Anda.
Dalam file Client.cs ubah nama subjek sertifikat layanan X.509 agar sesuai dengan nama komputer host jarak jauh yang sepenuhnya memenuhi syarat, bukan localhost.
Di komputer klien, luncurkan Client.exe dari jendela prompt perintah.
Jika klien dan layanan tidak dapat berkomunikasi, lihat Tips Pemecahan Masalah untuk Sampel WCF.
Untuk membersihkan setelah pengujian sampel
- Jalankan Cleanup.bat di folder sampel setelah Anda selesai menjalankan sampel.