Penyedia Token SAML

Sampel ini menunjukkan cara menerapkan penyedia token SAML klien kustom. Penyedia token di Windows Communication Foundation (WCF) digunakan untuk menyediakan kredensial ke infrastruktur keamanan. Penyedia token secara umum memeriksa target dan mengeluarkan kredensial yang sesuai sehingga infrastruktur keamanan dapat mengamankan pesan. WCF dikirim dengan Penyedia Token Manajer Kredensial default. WCF juga dilengkapi dengan penyedia token CardSpace. Penyedia token kustom berguna dalam kasus berikut:

  • Jika Anda memiliki penyimpanan kredensial yang tidak dapat dioperasikan oleh penyedia token ini.

  • Jika Anda ingin menyediakan mekanisme kustom Anda sendiri untuk mengubah kredensial dari saat pengguna memberikan informasi hingga saat kerangka kerja klien WCF menggunakan kredensial tersebut.

  • Jika Anda membangun token kustom.

Sampel ini menunjukkan cara membangun penyedia token kustom yang memungkinkan token SAML yang diperoleh dari luar kerangka kerja klien WCF untuk digunakan.

Untuk meringkas, sampel ini menunjukkan hal berikut:

  • Bagaimana klien dapat dikonfigurasi dengan penyedia token kustom.

  • Bagaimana token SAML dapat diteruskan ke kredensial klien kustom.

  • Bagaimana token SAML disediakan untuk kerangka kerja klien WCF.

  • Cara server diautentikasi oleh klien menggunakan sertifikat X.509 server.

Layanan ini mengekspos dua titik akhir untuk berkomunikasi dengan layanan, yang ditentukan menggunakan file konfigurasi App.config. Setiap titik akhir terdiri dari alamat, pengikatan, dan kontrak. Pengikatan dikonfigurasi dengan standar wsFederationHttpBinding, yang menggunakan Keamanan Pesan. Satu titik akhir mengharapkan klien untuk mengautentikasi dengan token SAML yang menggunakan kunci bukti simetris sementara yang lain mengharapkan klien untuk mengautentikasi dengan token SAML yang menggunakan kunci bukti asimetris. Layanan ini juga mengonfigurasi sertifikat layanan menggunakan perilaku serviceCredentials. Perilaku serviceCredentials ini memungkinkan Anda untuk mengonfigurasi sertifikat layanan. Sertifikat layanan digunakan oleh klien untuk mengautentikasi layanan dan memberikan perlindungan pesan. Konfigurasi berikut mereferensikan sertifikat "localhost" yang diinstal selama penyiapan sampel seperti yang dijelaskan dalam instruksi penyiapan di akhir topik ini. Perilaku ini serviceCredentials juga memungkinkan Anda mengonfigurasi sertifikat yang dipercaya untuk menandatangani token SAML. Konfigurasi berikut mereferensikan sertifikat 'Alice' yang diinstal selama sampel.

<system.serviceModel>
 <services>
  <service
          name="Microsoft.ServiceModel.Samples.CalculatorService"
          behaviorConfiguration="CalculatorServiceBehavior">
   <host>
    <baseAddresses>
     <!-- configure base address provided by host -->
     <add
  baseAddress="http://localhost:8000/servicemodelsamples/service/" />
    </baseAddresses>
   </host>
   <!-- use base address provided by host -->
   <!-- Endpoint that expect SAML tokens with Symmetric proof keys -->
   <endpoint address="calc/symm"
             binding="wsFederationHttpBinding"
             bindingConfiguration="Binding1"
             contract="Microsoft.ServiceModel.Samples.ICalculator" />
   <!-- Endpoint that expect SAML tokens with Asymmetric proof keys -->
   <endpoint address="calc/asymm"
             binding="wsFederationHttpBinding"
             bindingConfiguration="Binding2"
             contract="Microsoft.ServiceModel.Samples.ICalculator" />
  </service>
 </services>

 <bindings>
  <wsFederationHttpBinding>
   <!-- Binding that expect SAML tokens with Symmetric proof keys -->
   <binding name="Binding1">
    <security mode="Message">
     <message negotiateServiceCredential ="false"
              issuedKeyType="SymmetricKey"
              issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"  />
    </security>
   </binding>
   <!-- Binding that expect SAML tokens with Asymmetric proof keys -->
   <binding name="Binding2">
    <security mode="Message">
     <message negotiateServiceCredential ="false"
              issuedKeyType="AsymmetricKey"
              issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"  />
    </security>
   </binding>
  </wsFederationHttpBinding>
 </bindings>

 <behaviors>
  <serviceBehaviors>
   <behavior name="CalculatorServiceBehavior">
    <!--
    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.
    -->
    <serviceCredentials>
     <!-- Set allowUntrustedRsaIssuers to true to allow self-signed, asymmetric key based SAML tokens -->
     <issuedTokenAuthentication allowUntrustedRsaIssuers ="true" >
      <!-- Add Alice to the list of certs trusted to issue SAML tokens -->
      <knownCertificates>
       <add storeLocation="LocalMachine"
            storeName="TrustedPeople"
            x509FindType="FindBySubjectName"
            findValue="Alice"/>
      </knownCertificates>
     </issuedTokenAuthentication>
     <serviceCertificate storeLocation="LocalMachine"
                         storeName="My"
                         x509FindType="FindBySubjectName"
                         findValue="localhost"  />
    </serviceCredentials>
   </behavior>
  </serviceBehaviors>
 </behaviors>

</system.serviceModel>

Langkah-langkah berikut menunjukkan cara mengembangkan penyedia token SAML kustom dan mengintegrasikannya dengan WCF: kerangka kerja keamanan:

  1. Tulis penyedia token SAML kustom.

    Contoh mengimplementasikan penyedia token SAML kustom yang mengembalikan token keamanan berdasarkan pernyataan SAML yang disediakan saat pembuatan.

    Untuk melakukan tugas ini, penyedia token kustom merupakan turunan dari kelas SecurityTokenProvider dan mengoverride metode GetTokenCore. Metode ini membuat dan mengembalikan sebuah baru SecurityToken.

    protected override SecurityToken GetTokenCore(TimeSpan timeout)
    {
     // Create a SamlSecurityToken from the provided assertion
     SamlSecurityToken samlToken = new SamlSecurityToken(assertion);
    
     // Create a SecurityTokenSerializer that will be used to
     // serialize the SamlSecurityToken
     WSSecurityTokenSerializer ser = new WSSecurityTokenSerializer();
     // Create a memory stream to write the serialized token into
     // Use an initial size of 64Kb
     MemoryStream s = new MemoryStream(UInt16.MaxValue);
    
     // Create an XmlWriter over the stream
     XmlWriter xw = XmlWriter.Create(s);
    
     // Write the SamlSecurityToken into the stream
     ser.WriteToken(xw, samlToken);
    
     // Seek back to the beginning of the stream
     s.Seek(0, SeekOrigin.Begin);
    
     // Load the serialized token into a DOM
     XmlDocument dom = new XmlDocument();
     dom.Load(s);
    
     // Create a KeyIdentifierClause for the SamlSecurityToken
     SamlAssertionKeyIdentifierClause samlKeyIdentifierClause = samlToken.CreateKeyIdentifierClause<SamlAssertionKeyIdentifierClause>();
    
    // Return a GenericXmlToken from the XML for the
    // SamlSecurityToken, the proof token, the valid from and valid
    // until times from the assertion and the key identifier clause
    // created above
    return new GenericXmlSecurityToken(dom.DocumentElement, proofToken, assertion.Conditions.NotBefore, assertion.Conditions.NotOnOrAfter, samlKeyIdentifierClause, samlKeyIdentifierClause, null);
    }
    
  2. Tulis manajer token keamanan kustom.

    Kelas SecurityTokenManager digunakan untuk membuat SecurityTokenProvider yang dikhususkan untuk SecurityTokenRequirement yang diteruskan melalui metode CreateSecurityTokenProvider. Manajer token keamanan juga digunakan untuk membuat pengautentikasi token dan serializer token, tetapi tidak tercakup oleh sampel ini. Dalam sampel ini, manajer token keamanan kustom mewarisi dari ClientCredentialsSecurityTokenManager kelas dan mengambil alih CreateSecurityTokenProvider metode untuk mengembalikan penyedia token SAML kustom ketika persyaratan token yang diteruskan menunjukkan bahwa token SAML diminta. Jika kelas kredensial klien (lihat langkah 3) belum menentukan pernyataan, manajer token keamanan membuat instans yang sesuai.

    public class SamlSecurityTokenManager : ClientCredentialsSecurityTokenManager
    {
     SamlClientCredentials samlClientCredentials;
    
     public SamlSecurityTokenManager ( SamlClientCredentials samlClientCredentials)
      : base(samlClientCredentials)
     {
      // Store the creating client credentials
      this.samlClientCredentials = samlClientCredentials;
     }
    
     public override SecurityTokenProvider CreateSecurityTokenProvider ( SecurityTokenRequirement tokenRequirement )
     {
      // If token requirement matches SAML token return the
      // custom SAML token provider
      if (tokenRequirement.TokenType == SecurityTokenTypes.Saml ||
          tokenRequirement.TokenType == "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1")
      {
       // Retrieve the SAML assertion and proof token from the
       // client credentials
       SamlAssertion assertion = this.samlClientCredentials.Assertion;
       SecurityToken prooftoken = this.samlClientCredentials.ProofToken;
    
       // If either the assertion of proof token is null...
       if (assertion == null || prooftoken == null)
       {
        // ...get the SecurityBindingElement and then the
        // specified algorithm suite
        SecurityBindingElement sbe = null;
        SecurityAlgorithmSuite sas = null;
    
        if ( tokenRequirement.TryGetProperty<SecurityBindingElement> ( "http://schemas.microsoft.com/ws/2006/05/servicemodel/securitytokenrequirement/SecurityBindingElement", out sbe))
        {
         sas = sbe.DefaultAlgorithmSuite;
        }
    
        // If the token requirement is for a SymmetricKey based token..
        if (tokenRequirement.KeyType == SecurityKeyType.SymmetricKey)
        {
         // Create a symmetric proof token
         prooftoken = SamlUtilities.CreateSymmetricProofToken ( tokenRequirement.KeySize );
         // and a corresponding assertion based on the claims specified in the client credentials
         assertion = SamlUtilities.CreateSymmetricKeyBasedAssertion ( this.samlClientCredentials.Claims, new X509SecurityToken ( samlClientCredentials.ClientCertificate.Certificate ), new X509SecurityToken ( samlClientCredentials.ServiceCertificate.DefaultCertificate ), (BinarySecretSecurityToken)prooftoken, sas);
        }
        // otherwise...
        else
        {
         // Create an asymmetric proof token
         prooftoken = SamlUtilities.CreateAsymmetricProofToken();
         // and a corresponding assertion based on the claims
         // specified in the client credentials
         assertion = SamlUtilities.CreateAsymmetricKeyBasedAssertion ( this.samlClientCredentials.Claims, prooftoken, sas );
        }
       }
    
       // Create a SamlSecurityTokenProvider based on the assertion and proof token
       return new SamlSecurityTokenProvider(assertion, prooftoken);
      }
      // otherwise use base implementation
      else
      {
       return base.CreateSecurityTokenProvider(tokenRequirement);
      }
    }
    
  3. Tulis kredensial klien kustom.

    Kelas kredensial klien digunakan untuk mewakili kredensial yang dikonfigurasi untuk proksi klien dan membuat pengelola token keamanan yang digunakan untuk mendapatkan pengautentikasi token, penyedia token, dan penyeri token.

    public class SamlClientCredentials : ClientCredentials
    {
     ClaimSet claims;
     SamlAssertion assertion;
     SecurityToken proofToken;
    
     public SamlClientCredentials() : base()
     {
      // Set SupportInteractive to false to suppress Cardspace UI
      base.SupportInteractive = false;
     }
    
     protected SamlClientCredentials(SamlClientCredentials other) : base ( other )
     {
      // Just do reference copy given sample nature
      this.assertion = other.assertion;
      this.claims = other.claims;
      this.proofToken = other.proofToken;
     }
    
     public SamlAssertion Assertion { get { return assertion; } set { assertion = value; } }
    
     public SecurityToken ProofToken { get { return proofToken; } set { proofToken = value; } }
     public ClaimSet Claims { get { return claims; } set { claims = value; } }
    
     protected override ClientCredentials CloneCore()
     {
      return new SamlClientCredentials(this);
     }
    
     public override SecurityTokenManager CreateSecurityTokenManager()
     {
      // return custom security token manager
      return new SamlSecurityTokenManager(this);
     }
    }
    
  4. Konfigurasikan klien untuk menggunakan kredensial klien kustom.

    Sampel menghapus kelas kredensial klien default dan menyediakan kelas kredensial klien baru sehingga klien dapat menggunakan kredensial klien kustom.

    // Create new credentials class
    SamlClientCredentials samlCC = new SamlClientCredentials();
    
    // Set the client certificate. This is the cert that will be used to sign the SAML token in the symmetric proof key case
    samlCC.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "Alice");
    
    // Set the service certificate. This is the cert that will be used to encrypt the proof key in the symmetric proof key case
    samlCC.ServiceCertificate.SetDefaultCertificate(StoreLocation.CurrentUser, StoreName.TrustedPeople, X509FindType.FindBySubjectName, "localhost");
    
    // Create some claims to put in the SAML assertion
    IList<Claim> claims = new List<Claim>();
    claims.Add(Claim.CreateNameClaim(samlCC.ClientCertificate.Certificate.Subject));
    ClaimSet claimset = new DefaultClaimSet(claims);
    samlCC.Claims = claimset;
    
    // set new credentials
    client.ChannelFactory.Endpoint.Behaviors.Remove(typeof(ClientCredentials));
    client.ChannelFactory.Endpoint.Behaviors.Add(samlCC);
    

Pada layanan, klaim yang terkait dengan pemanggil ditampilkan. 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 dihost sendiri 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 file batch Setup.bat membuat sertifikat server yang akan digunakan. Variabel %SERVER_NAME% menentukan nama server. Ubah variabel ini untuk menentukan nama server Anda sendiri. Nilai default dalam file batch ini adalah localhost.

    Sertifikat disimpan di penyimpanan Saya (Pribadi) di bawah lokasi penyimpanan LocalMachine.

    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
    
  • Menginstal 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.

    certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r LocalMachine -s TrustedPeople
    
  • Membuat sertifikat penerbit.

    Baris berikut dari file batch Setup.bat membuat sertifikat penerbit yang akan digunakan. Variabel %USER_NAME% menentukan nama pengeluar sertifikat. Ubah variabel ini untuk menentukan nama pengeluar sertifikat Anda sendiri. Nilai default dalam file batch ini adalah Alice.

    Sertifikat disimpan di penyimpanan "My store" di bawah lokasi penyimpanan "CurrentUser".

    echo ************
    echo Server cert setup starting
    echo %SERVER_NAME%
    echo ************
    echo making server cert
    echo ************
    makecert.exe -sr CurrentUser -ss My -a sha1 -n CN=%USER_NAME% -sky exchange -pe
    
  • Menginstal sertifikat penerbit ke penyimpanan sertifikat tepercaya server.

    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 server dengan sertifikat penerbit tidak diperlukan.

    certmgr.exe -add -r CurrentUser -s My -c -n %USER_NAME% -r LocalMachine -s TrustedPeople
    

Untuk menyiapkan dan membangun sampel

  1. Pastikan Anda telah melakukan Prosedur Penyiapan One-Time untuk Sampel Windows Communication Foundation.

  2. Untuk membangun solusi, ikuti instruksi dalam Membangun Sampel Windows Communication Foundation.

Nota

Jika Anda menggunakan Svcutil.exe untuk meregenerasi konfigurasi untuk sampel ini, pastikan untuk mengubah nama titik akhir dalam konfigurasi klien agar sesuai dengan kode klien.

Untuk menjalankan sampel pada komputer yang sama

  1. Jalankan Setup.bat dari folder penginstalan sampel di dalam prompt perintah Visual Studio yang dijalankan dengan hak istimewa administrator. Ini menginstal semua sertifikat yang diperlukan untuk menjalankan sampel.

    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.

  2. Luncurkan Service.exe dari service\bin.

  3. Luncurkan Client.exe dari \client\bin. Aktivitas klien ditampilkan pada aplikasi konsol klien.

  4. Jika klien dan layanan tidak dapat berkomunikasi, lihat Tips Pemecahan Masalah untuk Sampel WCF.

Untuk menjalankan contoh program di berbagai komputer

  1. Buat direktori di komputer layanan untuk biner layanan.

  2. Salin file program layanan ke direktori layanan pada komputer layanan. Salin juga file Setup.bat dan Cleanup.bat ke komputer layanan.

  3. Anda harus memiliki sertifikat server dengan nama subjek yang berisi nama domain komputer yang sepenuhnya memenuhi syarat. File Service.exe.config harus diperbarui untuk mencerminkan nama sertifikat baru ini. Anda dapat membuat sertifikat server dengan memodifikasi file batch Setup.bat. Perhatikan bahwa file setup.bat harus dijalankan di jendela Perintah Pengembang untuk Visual Studio yang dibuka dengan hak istimewa administrator. Anda harus mengatur %SERVER_NAME% variabel ke nama host komputer yang sepenuhnya memenuhi syarat yang digunakan untuk menghosting layanan.

  4. Salin sertifikat server ke penyimpanan CurrentUser-TrustedPeople klien. Langkah ini tidak diperlukan ketika sertifikat server dikeluarkan oleh penerbit tepercaya klien.

  5. Dalam file Service.exe.config di komputer layanan, ubah nilai alamat dasar untuk menentukan nama komputer yang sepenuhnya memenuhi syarat alih-alih localhost.

  6. Pada komputer servis, jalankan Service.exe dari command prompt.

  7. Salin file program klien dari folder \client\bin\, di bawah folder khusus bahasa, ke komputer klien.

  8. Dalam file Client.exe.config di komputer klien, ubah nilai alamat titik akhir agar sesuai dengan alamat baru layanan Anda.

  9. Pada komputer klien, luncurkan Client.exe dari jendela prompt perintah.

  10. Jika klien dan layanan tidak dapat berkomunikasi, lihat Tips Pemecahan Masalah untuk Sampel WCF.

Untuk membersihkan setelah pengujian sampel

  1. Jalankan Cleanup.bat di folder sampel setelah Anda selesai menjalankan sampel.