Megosztás a következőn keresztül:


Egyéni jogkivonat

Ez a minta bemutatja, hogyan vehet fel egyéni jogkivonat-implementációt a Windows Communication Foundation (WCF) alkalmazásba. A példa az CreditCardToken ügyfél hitelkártyáival kapcsolatos információk biztonságos átadására szolgál a szolgáltatásnak. A jogkivonat a WS-Security üzenetfejlécben lesz átadva, és a szimmetrikus biztonsági kötési elem, valamint az üzenettörzs és más üzenetfejlécek használatával van aláírva és titkosítva. Ez akkor hasznos, ha a beépített jogkivonatok nem elegendőek. Ez a minta bemutatja, hogyan biztosíthat egyéni biztonsági jogkivonatot egy szolgáltatásnak a beépített jogkivonatok használata helyett. A szolgáltatás megvalósít egy szerződést, amely egy kérés-válasz kommunikációs mintát határoz meg.

Feljegyzés

A minta telepítési eljárása és összeállítási utasításai a témakör végén találhatók.

Összegzésként ez a minta a következőket mutatja be:

  • Hogyan adhat át egy ügyfél egyéni biztonsági jogkivonatot egy szolgáltatásnak.

  • Hogyan használhatja fel és érvényesítheti a szolgáltatás az egyéni biztonsági jogkivonatokat.

  • Hogyan szerezheti be a WCF szolgáltatáskód a kapott biztonsági jogkivonatokkal kapcsolatos információkat, beleértve az egyéni biztonsági jogkivonatot is.

  • A kiszolgáló X.509-tanúsítványának használata az üzenettitkosításhoz és aláíráshoz használt szimmetrikus kulcs védelmére.

Ügyfél-hitelesítés egyéni biztonsági jogkivonat használatával

A szolgáltatás egyetlen végpontot tesz elérhetővé, amely programozott módon jön létre a használatával BindingHelper és EchoServiceHost az osztályokkal. A végpont egy címből, egy kötésből és egy szerződésből áll. A kötés egyéni kötéssel SymmetricSecurityBindingElement van konfigurálva az and HttpTransportBindingElement. Ez a minta egy szolgáltatás X.509-tanúsítványának használatára állítja be a SymmetricSecurityBindingElement szimmetrikus kulcs átvitel közbeni védelmére, valamint egy egyéni CreditCardToken WS-Security-üzenet fejlécében aláírt és titkosított biztonsági jogkivonatként való átadására. A viselkedés meghatározza az ügyfél-hitelesítéshez használandó szolgáltatás hitelesítő adatait, valamint az X.509 szolgáltatás tanúsítványával kapcsolatos információkat.

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);
    }
}

Ha hitelkártya-jogkivonatot szeretne használni az üzenetben, a minta egyéni szolgáltatás hitelesítő adataival biztosítja ezt a funkciót. A szolgáltatás hitelesítő adatai osztály az CreditCardServiceCredentials osztályban található, és a metódusban hozzáadódik a szolgáltatás gazdagépének EchoServiceHost.InitializeRuntime viselkedésgyűjteményeihez.

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();
    }
}

Az ügyfélvégpont a szolgáltatásvégponthoz hasonlóan van konfigurálva. Az ügyfél ugyanazt BindingHelper az osztályt használja kötés létrehozásához. A beállítás többi része az Client osztályban található. Az ügyfél beállítja a beállítási kódban található CreditCardToken X.509 szolgáltatástanúsítvány adatait is úgy, hogy hozzáad egy példányt CreditCardClientCredentials a megfelelő adatokkal az ügyfélvégpont viselkedési gyűjteményéhez. A minta X.509-tanúsítványt használ, amelynek tulajdonosi neve szolgáltatástanúsítványként van beállítva CN=localhost .

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();

Egyéni biztonsági jogkivonat implementálása

Ha egyéni biztonsági jogkivonatot szeretne engedélyezni a WCF-ben, hozzon létre egy objektumábrázolást az egyéni biztonsági jogkivonatról. A mintának ez a reprezentációja van az CreditCardToken osztályban. Az objektumábrázolás feladata az összes releváns biztonsági jogkivonat-információ megtartása, valamint a biztonsági jogkivonatban található biztonsági kulcsok listája. Ebben az esetben a hitelkártya biztonsági jogkivonata nem tartalmaz biztonsági kulcsot.

A következő szakasz azt ismerteti, hogy mit kell tenni annak érdekében, hogy az egyéni jogkivonatok átvitele a vezetéken keresztül történik, és amelyeket egy WCF-végpont használjon fel.

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; } }
}

Az egyéni hitelkártya-jogkivonat lekérése az üzenetbe és az üzenetből

A WCF biztonsági jogkivonat-szerializálói felelősek a biztonsági jogkivonatok objektumreprezentációjának létrehozásáért az xml-ből az üzenetben, valamint a biztonsági jogkivonatok XML-formájának létrehozásáért. Más funkciókért is felelősek, például a biztonsági jogkivonatokra mutató kulcsazonosítók olvasásáért és írásáért, de ez a példa csak a biztonsági jogkivonattal kapcsolatos funkciókat használja. Az egyéni jogkivonatok engedélyezéséhez saját biztonsági jogkivonat-szerializálót kell implementálnia. Ez a minta erre a célra használja az CreditCardSecurityTokenSerializer osztályt.

A szolgáltatásban az egyéni szerializáló beolvassa az egyéni jogkivonat XML-formáját, és létrehozza belőle az egyéni jogkivonat objektumábrázolását.

Az ügyfélen az osztály beírja CreditCardSecurityTokenSerializer a biztonsági jogkivonat objektumábrázolásában található információkat az XML-íróba.

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);
        }
    }
}

Jogkivonat-szolgáltatói és jogkivonat-hitelesítő osztályok létrehozása

Az ügyfél- és szolgáltatás hitelesítő adatai felelősek a biztonsági jogkivonat-kezelő példányának biztosításáért. A biztonsági jogkivonat-kezelő példány a jogkivonat-szolgáltatók, a jogkivonat-hitelesítők és a jogkivonat-szerializálók lekérésére szolgál.

A jogkivonat-szolgáltató az ügyfél- vagy szolgáltatás hitelesítő adatai alapján létrehozza a jogkivonat objektumábrázolását. A jogkivonat objektumábrázolása ezután a jogkivonat szerializálójának használatával lesz megírva az üzenetbe (az előző szakaszban tárgyalt).

A jogkivonat-hitelesítő ellenőrzi az üzenetbe érkező jogkivonatokat. A bejövő jogkivonat objektumábrázolását a jogkivonat szerializálója hozza létre. Ezt az objektumábrázolást ezután a rendszer érvényesítés céljából átadja a jogkivonat-hitelesítőnek. A jogkivonat sikeres érvényesítése után a jogkivonat-hitelesítő olyan objektumgyűjteményt IAuthorizationPolicy ad vissza, amely a jogkivonatban található információkat képviseli. Ezeket az információkat az üzenetfeldolgozás során felhasználjuk az engedélyezési döntések végrehajtására és az alkalmazás jogcímeinek megadására. Ebben a példában a hitelkártya-jogkivonat hitelesítője erre a célra használja CreditCardTokenAuthorizationPolicy .

A jogkivonat szerializálója a jogkivonat objektumábrázolásának lekérése a vezetékbe és a vezetékből. Erről az előző szakaszban olvashat.

Ebben a példában csak az ügyfélen használunk jogkivonat-szolgáltatót, a jogkivonat-hitelesítőt pedig csak a szolgáltatáson, mivel csak az ügyfél-szolgáltatás irányban szeretnénk továbbítani egy hitelkártya-jogkivonatot.

Az ügyfél funkciói a , CreditCardClientCredentialsSecurityTokenManager és CreditCardTokenProvider az CreditCardClientCredentialsosztályokban találhatók.

A szolgáltatásban a funkció a , CreditCardServiceCredentialsSecurityTokenManagerCreditCardTokenAuthenticator és CreditCardTokenAuthorizationPolicy az CreditCardServiceCredentialsosztályokban található.

    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;
        }
    }

A hívók adatainak megjelenítése

A hívó adatainak megjelenítéséhez használja az ServiceSecurityContext.Current.AuthorizationContext.ClaimSets alábbi mintakódot. Ez ServiceSecurityContext.Current.AuthorizationContext.ClaimSets az aktuális hívóhoz társított engedélyezési jogcímeket tartalmazza. A jogcímeket az osztály adja meg a CreditCardToken gyűjteményében 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";
}

A minta futtatásakor a műveleti kérelmek és a válaszok megjelennek az ügyfélkonzol ablakában. Nyomja le az ENTER billentyűt az ügyfélablakban az ügyfél leállításához.

Batch-fájl beállítása

A mintában szereplő Setup.bat kötegfájl lehetővé teszi a kiszolgáló megfelelő tanúsítványokkal való konfigurálását az IIS által üzemeltetett alkalmazás futtatásához, amely kiszolgálói tanúsítványalapú biztonságot igényel. Ezt a kötegfájlt úgy kell módosítani, hogy a számítógépeken is működjön, vagy nem üzemeltetett esetben működjön.

Az alábbiakban röviden áttekintheti a kötegfájlok különböző szakaszait, hogy azok a megfelelő konfigurációban való futtatásukhoz módosíthatók legyenek.

  • A kiszolgálótanúsítvány létrehozása:

    A batch fájl alábbi sorai Setup.bat létrehozzák a használni kívánt kiszolgálói tanúsítványt. A %SERVER_NAME% változó megadja a kiszolgáló nevét. Módosítsa ezt a változót a saját kiszolgáló nevének megadásához. Ebben a kötegfájlban az alapértelmezett a localhost. Ha módosítja a %SERVER_NAME% változót, át kell haladnia a Client.cs és Service.cs fájlokat, és a localhost összes példányát le kell cserélnie a Setup.bat szkriptben használt kiszolgálónévre.

    A tanúsítvány a Saját (Személyes) tárolóban van tárolva az LocalMachine áruház helye alatt. A tanúsítvány az IIS által üzemeltetett szolgáltatások LocalMachine áruházában van tárolva. A saját üzemeltetésű szolgáltatások esetében módosítania kell a kötegfájlt úgy, hogy az ügyféltanúsítványt a CurrentUser tárolóhelyén tárolja, a LocalMachine sztringet a CurrentUserre cserélve.

    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
    
  • A kiszolgálótanúsítvány telepítése az ügyfél megbízható tanúsítványtárolójába:

    A Setup.bat kötegfájl alábbi sorai másolja a kiszolgálótanúsítványt az ügyfél megbízható személyek tárolójába. Erre a lépésre azért van szükség, mert a Makecert.exe által létrehozott tanúsítványokat az ügyfélrendszer nem implicit módon megbízhatónak minősíti. Ha már rendelkezik olyan tanúsítvánnyal, amely egy ügyfél megbízható főtanúsítványában gyökerezik – például egy Microsoft által kiadott tanúsítványban –, nem szükséges az ügyféltanúsítvány-tároló kiszolgálótanúsítvánnyal való feltöltésének ez a lépése.

    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
    
  • Ahhoz, hogy az IIS által üzemeltetett szolgáltatásból hozzáférjen a tanúsítvány titkos kulcsához, a felhasználói fióknak, amelyen az IIS által üzemeltetett folyamat fut, megfelelő engedélyeket kell biztosítani a titkos kulcshoz. Ezt a Setup.bat szkript utolsó lépései hajtják végre.

    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
    

Feljegyzés

A Setup.bat kötegelt fájl úgy lett kialakítva, hogy egy Visual Studio parancssorból fusson. A Visual Studio parancssorában beállított PATH környezeti változó a Setup.bat szkript által igényelt végrehajtható fájlokat tartalmazó könyvtárra mutat.

A minta beállítása és létrehozása

  1. Győződjön meg arról, hogy elvégezte a Windows Communication Foundation-minták egyszeri beállítási eljárását.

  2. A megoldás létrehozásához kövesse a Windows Communication Foundation-minták készítésére vonatkozó utasításokat.

A minta futtatása ugyanazon a számítógépen

  1. Nyisson meg egy Visual Studio parancssori ablakot rendszergazdai jogosultságokkal, és futtassa a Setup.bat a minta telepítési mappából. Ez telepíti a minta futtatásához szükséges összes tanúsítványt. Győződjön meg arról, hogy az elérési út tartalmazza azt a mappát, amelyben Makecert.exe található.

Feljegyzés

A mintával végzett Cleanup.bat futtatásával távolítsa el a tanúsítványokat. Más biztonsági minták ugyanazokat a tanúsítványokat használják.

  1. Indítsa el a Client.exe az ügyfél\bin könyvtárból. Az ügyféltevékenység megjelenik az ügyfélkonzol-alkalmazásban.

  2. Ha az ügyfél és a szolgáltatás nem tud kommunikálni, olvassa el a WCF-minták hibaelhárítási Tippek című témakört.

A minta futtatása a számítógépen

  1. Hozzon létre egy címtárat a szolgáltatásszámítógépen a szolgáltatás bináris fájljaihoz.

  2. Másolja a szolgáltatásprogram fájljait a szolgáltatásszámítógép szolgáltatáskönyvtárába. Ne felejtse el másolni a CreditCardFile.txt; ellenkező esetben a hitelkártyahitelesítő nem tudja érvényesíteni az ügyféltől küldött hitelkártyaadatokat. Másolja a Setup.bat és Cleanup.bat fájlokat is a szolgáltatásszámítógépre.

  3. Rendelkeznie kell a számítógép teljes tartománynevét tartalmazó tulajdonosnévvel rendelkező kiszolgálótanúsítvánnyal. Létrehozhat egyet a Setup.bat használatával, ha a változót %SERVER_NAME% a szolgáltatást futtató számítógép teljes neveként módosítja. Vegye figyelembe, hogy a Setup.bat fájlt rendszergazdai jogosultságokkal megnyitott Fejlesztői parancssorban kell futtatni.

  4. Másolja a kiszolgálótanúsítványt az ügyfél CurrentUser-Trusted Kapcsolatok tárolójába. Ezt csak akkor kell megtennie, ha a kiszolgálói tanúsítványt nem megbízható kiállító állítja ki.

  5. A EchoServiceHost.cs fájlban módosítsa a tanúsítvány tulajdonosának nevét úgy, hogy a localhost helyett egy teljes számítógépnevet adjon meg.

  6. Másolja az ügyfélprogram fájljait a \client\bin\ mappából a nyelvspecifikus mappából az ügyfélszámítógépre.

  7. A Client.cs fájlban módosítsa a végpont címértékét, hogy megfeleljen a szolgáltatás új címének.

  8. A Client.cs fájlban módosítsa az X.509 szolgáltatás tanúsítvány tulajdonosának nevét úgy, hogy az megfeleljen a távoli gazdagép teljes számítógépnevének a localhost helyett.

  9. Az ügyfélszámítógépen indítsa el a Client.exe egy parancssori ablakból.

  10. Ha az ügyfél és a szolgáltatás nem tud kommunikálni, olvassa el a WCF-minták hibaelhárítási Tippek című témakört.

A minta utáni tisztítás

  1. A minta futtatása után futtassa a Cleanup.bat a mintamappában.