Dela via


Tokenautentisering

Det här exemplet visar hur du implementerar en anpassad tokenautentisering. En tokenautentisering i Windows Communication Foundation (WCF) används för att verifiera token som används med meddelandet, verifiera att den är självkonsekvent och autentisera den identitet som är associerad med token.

Anpassade tokenautentiseringsprogram är användbara i en mängd olika fall, till exempel:

  • När du vill åsidosätta standardautentiseringsmekanismen som är associerad med en token.

  • När du skapar en anpassad token.

Det här exemplet visar följande:

  • Hur en klient kan autentisera med ett användarnamn/lösenordspar.

  • Hur servern kan verifiera klientautentiseringsuppgifterna med hjälp av en anpassad tokenautentisering.

  • Så här kopplas WCF-tjänstkoden ihop med den anpassade tokenautentiseringen.

  • Hur servern kan autentiseras med hjälp av serverns X.509-certifikat.

Det här exemplet visar också hur anroparens identitet är tillgänglig från WCF efter autentiseringsprocessen för anpassad token.

Tjänsten exponerar en enskild slutpunkt för kommunikation med tjänsten, definierad med hjälp av konfigurationsfilen App.config. Slutpunkten består av en adress, en bindning och ett kontrakt. Bindningen konfigureras med en standard wsHttpBinding, med säkerhetsläget inställt på meddelande – standardläget för wsHttpBinding. Det här exemplet anger standarden wsHttpBinding för att använda autentisering med klientanvändarnamn. Tjänsten konfigurerar även tjänstcertifikatet med hjälp av serviceCredentials beteende. Med securityCredentials beteendet kan du ange ett tjänstcertifikat. Ett tjänstcertifikat används av en klient för att autentisera tjänsten och tillhandahålla meddelandeskydd. Följande konfiguration refererar till det localhost-certifikat som installerades under exempelkonfigurationen enligt beskrivningen i följande installationsanvisningar.

<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 address=""
                  binding="wsHttpBinding"
                  bindingConfiguration="Binding1"
                  contract="Microsoft.ServiceModel.Samples.ICalculator" />
      </service>
    </services>

    <bindings>
      <wsHttpBinding>
        <binding name="Binding1">
          <security mode="Message">
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>

    <behaviors>
      <serviceBehaviors>
        <behavior name="CalculatorServiceBehavior">
          <serviceDebug includeExceptionDetailInFaults="False" />
          <!--
          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>
            <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>

Klientslutpunktskonfigurationen består av ett konfigurationsnamn, en absolut adress för tjänstslutpunkten, bindningen och kontraktet. Klientbindningen konfigureras med lämplig Mode och clientCredentialType.

<system.serviceModel>
    <client>
      <endpoint name=""
                address="http://localhost:8000/servicemodelsamples/service"
                binding="wsHttpBinding"
                bindingConfiguration="Binding1"
                contract="Microsoft.ServiceModel.Samples.ICalculator">
      </endpoint>
    </client>

    <bindings>
      <wsHttpBinding>
        <binding name="Binding1">
          <security mode="Message">
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
  </system.serviceModel>

Klientimplementeringen anger användarnamnet och lösenordet som ska användas.

static void Main()
{
     ...
     client.ClientCredentials.UserNamePassword.UserName = username;
     client.ClientCredentials.UserNamePassword.Password = password;
     ...
}

Autentisering av anpassad token

Använd följande steg för att skapa en anpassad tokenautentisering:

  1. Skriv en anpassad tokenautentisering.

    Exemplet implementerar en anpassad tokenautentisering som verifierar att användarnamnet har ett giltigt e-postformat. Den härleder UserNameSecurityTokenAuthenticator. Den viktigaste metoden i den här klassen är ValidateUserNamePasswordCore(String, String). I den här metoden validerar autentiseringen formatet för användarnamnet och även att värdnamnet inte kommer från en falsk domän. Om båda villkoren uppfylls returneras en skrivskyddad samling IAuthorizationPolicy instanser som sedan används för att tillhandahålla anspråk som representerar den information som lagras i användarnamnstoken.

    protected override ReadOnlyCollection<IAuthorizationPolicy> ValidateUserNamePasswordCore(string userName, string password)
    {
        if (!ValidateUserNameFormat(userName))
            throw new SecurityTokenValidationException("Incorrect UserName format");
    
        ClaimSet claimSet = new DefaultClaimSet(ClaimSet.System, new Claim(ClaimTypes.Name, userName, Rights.PossessProperty));
        List<IIdentity> identities = new List<IIdentity>(1);
        identities.Add(new GenericIdentity(userName));
        List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>(1);
        policies.Add(new UnconditionalPolicy(ClaimSet.System, claimSet, DateTime.MaxValue.ToUniversalTime(), identities));
        return policies.AsReadOnly();
    }
    
  2. Ange en auktoriseringsprincip som returneras av en anpassad tokenautentisering.

    Det här exemplet tillhandahåller en egen implementering av IAuthorizationPolicy anropade UnconditionalPolicy som returnerar en uppsättning anspråk och identiteter som skickades till den i konstruktorn.

    class UnconditionalPolicy : IAuthorizationPolicy
    {
        String id = Guid.NewGuid().ToString();
        ClaimSet issuer;
        ClaimSet issuance;
        DateTime expirationTime;
        IList<IIdentity> identities;
    
        public UnconditionalPolicy(ClaimSet issuer, ClaimSet issuance, DateTime expirationTime, IList<IIdentity> identities)
        {
            if (issuer == null)
                throw new ArgumentNullException("issuer");
            if (issuance == null)
                throw new ArgumentNullException("issuance");
    
            this.issuer = issuer;
            this.issuance = issuance;
            this.identities = identities;
            this.expirationTime = expirationTime;
        }
    
        public string Id
        {
            get { return this.id; }
        }
    
        public ClaimSet Issuer
        {
            get { return this.issuer; }
        }
    
        public DateTime ExpirationTime
        {
            get { return this.expirationTime; }
        }
    
        public bool Evaluate(EvaluationContext evaluationContext, ref object state)
        {
            evaluationContext.AddToTarget(this, this.issuance);
    
            if (this.identities != null)
            {
                object value;
                IList<IIdentity> contextIdentities;
                if (!evaluationContext.Properties.TryGetValue("Identities", out value))
                {
                    contextIdentities = new List<IIdentity>(this.identities.Count);
                    evaluationContext.Properties.Add("Identities", contextIdentities);
                }
                else
                {
                    contextIdentities = value as IList<IIdentity>;
                }
                foreach (IIdentity identity in this.identities)
                {
                    contextIdentities.Add(identity);
                }
            }
    
            evaluationContext.RecordExpirationTime(this.expirationTime);
            return true;
        }
    }
    
  3. Skriv en anpassad säkerhetstokenhanterare.

    SecurityTokenManager Används för att skapa en SecurityTokenAuthenticator för specifika SecurityTokenRequirement objekt som skickas till den CreateSecurityTokenAuthenticator i -metoden. Säkerhetstokenhanteraren används också för att skapa tokenprovidrar och token-serialiserare, men de omfattas inte av det här exemplet. I det här exemplet ärver den anpassade säkerhetstokenhanteraren från ServiceCredentialsSecurityTokenManager klassen och åsidosätter CreateSecurityTokenAuthenticator metoden för att returnera anpassad autentisering av användarnamnstoken när kraven för godkänd token anger att användarnamnsautentisering begärs.

    public class MySecurityTokenManager : ServiceCredentialsSecurityTokenManager
    {
        MyUserNameCredential myUserNameCredential;
    
        public MySecurityTokenManager(MyUserNameCredential myUserNameCredential)
            : base(myUserNameCredential)
        {
            this.myUserNameCredential = myUserNameCredential;
        }
    
        public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver)
        {
            if (tokenRequirement.TokenType ==  SecurityTokenTypes.UserName)
            {
                outOfBandTokenResolver = null;
                return new MyTokenAuthenticator();
            }
            else
            {
                return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver);
            }
        }
    }
    
  4. Skriv en autentiseringsuppgift för anpassad tjänst.

    Klassen för tjänstautentiseringsuppgifter används för att representera de autentiseringsuppgifter som är konfigurerade för tjänsten och skapar en säkerhetstokenhanterare som används för att hämta tokenautentisering, tokenprovidrar och token-serialiserare.

    public class MyUserNameCredential : ServiceCredentials
    {
    
        public MyUserNameCredential()
            : base()
        {
        }
    
        protected override ServiceCredentials CloneCore()
        {
            return new MyUserNameCredential();
        }
    
        public override SecurityTokenManager CreateSecurityTokenManager()
        {
            return new MySecurityTokenManager(this);
        }
    
    }
    
  5. Konfigurera tjänsten så att den använder autentiseringsuppgifterna för anpassade tjänster.

    För att tjänsten ska kunna använda autentiseringsuppgifterna för anpassade tjänster tar vi bort standardklassen för tjänstautentiseringsuppgifter efter att ha avbildat tjänstcertifikatet som redan är förkonfigurerat i standardtjänstens autentiseringsuppgifter, och konfigurerar den nya instansen av tjänstautentiseringsuppgifter för att använda de förkonfigurerade tjänstcertifikaten och lägga till den nya instansen av tjänstautentiseringsuppgifter i tjänstbeteenden.

    ServiceCredentials sc = serviceHost.Credentials;
    X509Certificate2 cert = sc.ServiceCertificate.Certificate;
    MyUserNameCredential serviceCredential = new MyUserNameCredential();
    serviceCredential.ServiceCertificate.Certificate = cert;
    serviceHost.Description.Behaviors.Remove((typeof(ServiceCredentials)));
    serviceHost.Description.Behaviors.Add(serviceCredential);
    

Om du vill visa uppringarens information kan du använda det PrimaryIdentity som visas i följande kod. Innehåller Current anspråksinformation om den aktuella anroparen.

static void DisplayIdentityInformation()
{
    Console.WriteLine("\t\tSecurity context identity  :  {0}",
            ServiceSecurityContext.Current.PrimaryIdentity.Name);
     return;
}

När du kör exemplet visas åtgärdsbegäranden och svar i klientkonsolfönstret. Tryck på RETUR i klientfönstret för att stänga av klienten.

Konfigurera Batch-fil

Med Setup.bat batchfil som ingår i det här exemplet kan du konfigurera servern med relevanta certifikat för att köra ett program med egen värd som kräver servercertifikatbaserad säkerhet. Den här batchfilen måste ändras för att fungera mellan datorer eller för att fungera i ett fall som inte är värdbaserat.

Följande ger en kort översikt över de olika avsnitten i batchfilerna så att de kan ändras så att de körs i lämplig konfiguration.

  • Skapa servercertifikatet.

    Följande rader från Setup.bat batchfil skapar det servercertifikat som ska användas. Variabeln %SERVER_NAME% anger servernamnet. Ändra den här variabeln för att ange ditt eget servernamn. Standardvärdet i den här batchfilen är localhost.

    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
    
  • Installera servercertifikatet i klientens betrodda certifikatarkiv.

    Följande rader i Setup.bat batchfil kopierar servercertifikatet till klientarkivet för betrodda personer. Det här steget krävs eftersom certifikat som genereras av Makecert.exe inte är implicit betrodda av klientsystemet. Om du redan har ett certifikat som är rotat i ett klientbetrott rotcertifikat, till exempel ett Microsoft-utfärdat certifikat, krävs inte det här steget för att fylla i klientcertifikatarkivet med servercertifikatet.

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

    Kommentar

    Batch-installationsfilen är utformad för att köras från en Windows SDK-kommandotolk. Det kräver att miljövariabeln MSSDK pekar på katalogen där SDK:et är installerat. Den här miljövariabeln anges automatiskt i en Windows SDK-kommandotolk.

Så här konfigurerar och skapar du exemplet

  1. Kontrollera att du har utfört engångsinstallationsproceduren för Windows Communication Foundation-exempel.

  2. Skapa lösningen genom att följa anvisningarna i Skapa Windows Communication Foundation-exempel.

Så här kör du exemplet på samma dator

  1. Kör Setup.bat från exempelinstallationsmappen i en Visual Studio-kommandotolk som öppnas med administratörsbehörighet. Detta installerar alla certifikat som krävs för att köra exemplet.

    Kommentar

    Den Setup.bat batchfilen är utformad för att köras från en Visual Studio-kommandotolk. Variabeln PATH-miljö som angetts i Visual Studio-kommandotolken pekar på katalogen som innehåller körbara filer som krävs av Setup.bat skriptet.

  2. Starta service.exe från service\bin.

  3. Starta client.exe från \client\bin. Klientaktiviteten visas i klientkonsolprogrammet.

  4. Om klienten och tjänsten inte kan kommunicera kan du läsa Felsökningstips för WCF-exempel.

Så här kör du exemplet mellan datorer

  1. Skapa en katalog på tjänstdatorn för tjänstens binärfiler.

  2. Kopiera tjänstprogramfilerna till tjänstkatalogen på tjänstdatorn. Kopiera även Setup.bat- och Cleanup.bat-filerna till tjänstdatorn.

  3. Du måste ha ett servercertifikat med ämnesnamnet som innehåller datorns fullständigt kvalificerade domännamn. Service App.config-filen måste uppdateras för att återspegla det nya certifikatnamnet. Du kan skapa en med hjälp av Setup.bat om du anger variabeln %SERVER_NAME% till fullständigt kvalificerat värdnamn för den dator där tjänsten ska köras. Observera att filen setup.bat måste köras från en kommandotolk för utvecklare för Visual Studio som öppnas med administratörsbehörighet.

  4. Kopiera servercertifikatet till CurrentUser-Trusted Personer-arkivet för klienten. Du behöver inte göra detta förutom när servercertifikatet utfärdas av en betrodd utfärdare av klienten.

  5. I filen App.config på tjänstdatorn ändrar du värdet för basadressen för att ange ett fullständigt kvalificerat datornamn i stället för localhost.

  6. På tjänstdatorn kör du service.exe från en kommandotolk.

  7. Kopiera klientprogramfilerna från mappen \client\bin\ under den språkspecifika mappen till klientdatorn.

  8. I filen Client.exe.config på klientdatorn ändrar du slutpunktens adressvärde så att det matchar tjänstens nya adress.

  9. Starta Client.exe från en kommandotolk på klientdatorn.

  10. Om klienten och tjänsten inte kan kommunicera kan du läsa Felsökningstips för WCF-exempel.

Rensa efter exemplet

  1. Kör Cleanup.bat i exempelmappen när du har kört exemplet.