Zaufana usługa fasady

W przykładzie TrustedFacade pokazano, jak przepływać informacje o tożsamości obiektu wywołującego z jednej usługi do innej przy użyciu infrastruktury zabezpieczeń programu Windows Communication Foundation (WCF).

Typowym wzorcem projektowym jest uwidacznianie funkcji udostępnianych przez usługę w sieci publicznej przy użyciu usługi fasady. Usługa fasady zazwyczaj znajduje się w sieci obwodowej (nazywanej również strefą DMZ, strefą zdemilitaryzowaną i podsiecią ekranowaną) i komunikuje się z usługą zaplecza, która implementuje logikę biznesową i ma dostęp do danych wewnętrznych. Kanał komunikacyjny między usługą fasady a usługą zaplecza przechodzi przez zaporę i jest zwykle ograniczony tylko do jednego celu.

Ten przykład składa się z następujących składników:

  • Klient kalkulatora

  • Usługa fasady kalkulatora

  • Kalkulator usługi zaplecza

Usługa fasady jest odpowiedzialna za weryfikowanie żądania i uwierzytelnianie wywołującego. Po pomyślnym uwierzytelnieniu i weryfikacji przekazuje żądanie do usługi zaplecza przy użyciu kontrolowanego kanału komunikacyjnego z sieci obwodowej do sieci wewnętrznej. W ramach przekazanego żądania usługa fasady zawiera informacje o tożsamości obiektu wywołującego, dzięki czemu usługa zaplecza może używać tych informacji w przetwarzaniu. Tożsamość elementu wywołującego jest przesyłana przy użyciu tokenu zabezpieczającego Username wewnątrz nagłówka komunikatu Security . W przykładzie użyto infrastruktury zabezpieczeń programu WCF do przesyłania i wyodrębniania tych informacji z nagłówka Security .

Ważne

Usługa zaplecza ufa usłudze fasady w celu uwierzytelnienia elementu wywołującego. W związku z tym usługa zaplecza nie uwierzytelnia obiektu wywołującego ponownie; używa informacji o tożsamości dostarczonych przez usługę fasady w przesłanym dalej żądaniu. Ze względu na tę relację zaufania usługa zaplecza musi uwierzytelniać usługę fasady, aby upewnić się, że przesłany dalej komunikat pochodzi z zaufanego źródła — w tym przypadku usługa fasady.

Implementacja

W tym przykładzie istnieją dwie ścieżki komunikacyjne. Po pierwsze jest między klientem a usługą fasady, druga jest między usługą fasady a usługą zaplecza.

Ścieżka komunikacji między klientem a usługą fasady

Klient do ścieżki komunikacji usługi fasady używa z wsHttpBinding typem UserName poświadczeń klienta. Oznacza to, że klient używa nazwy użytkownika i hasła do uwierzytelniania w usłudze fasady, a usługa fasady używa certyfikatu X.509 do uwierzytelniania klienta. Konfiguracja powiązania wygląda podobnie do poniższego przykładu.

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

Usługa fasady uwierzytelnia obiekt wywołujący przy użyciu implementacji niestandardowej UserNamePasswordValidator . W celach demonstracyjnych uwierzytelnianie zapewnia tylko, że nazwa użytkownika osoby wywołującej jest zgodna z przedstawionym hasłem. W rzeczywistej sytuacji użytkownik jest prawdopodobnie uwierzytelniany przy użyciu usługi Active Directory lub niestandardowego dostawcy członkostwa ASP.NET. Implementacja modułu sprawdzania poprawności znajduje się w FacadeService.cs pliku.

public class MyUserNamePasswordValidator : UserNamePasswordValidator
{
    public override void Validate(string userName, string password)
    {
        // check that username matches password
        if (null == userName || userName != password)
        {
            Console.WriteLine("Invalid username or password");
            throw new SecurityTokenValidationException(
                       "Invalid username or password");
        }
    }
}

Niestandardowy moduł sprawdzania poprawności jest skonfigurowany do użycia wewnątrz serviceCredentials zachowania w pliku konfiguracji usługi fasady. To zachowanie jest również używane do konfigurowania certyfikatu X.509 usługi.

<behaviors>
  <serviceBehaviors>
    <behavior name="FacadeServiceBehavior">
      <!--The serviceCredentials behavior allows you to define -->
      <!--a service certificate. -->
      <!--A service certificate is used by the service to  -->
      <!--authenticate itself to its clients and to provide  -->
      <!--message protection. -->
      <!--This configuration references the "localhost"  -->
      <!--certificate installed during the setup instructions. -->
      <serviceCredentials>
        <serviceCertificate
               findValue="localhost"
               storeLocation="LocalMachine"
               storeName="My"
               x509FindType="FindBySubjectName" />
        <userNameAuthentication userNamePasswordValidationMode="Custom"
            customUserNamePasswordValidatorType=
           "Microsoft.ServiceModel.Samples.MyUserNamePasswordValidator,
            FacadeService"/>
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>

Ścieżka komunikacji między usługą fasady a usługą zaplecza

Usługa fasady do ścieżki komunikacji usługi zaplecza używa elementu customBinding składającego się z kilku elementów powiązania. To powiązanie wykonuje dwie rzeczy. Uwierzytelnia usługę fasady i usługę zaplecza, aby upewnić się, że komunikacja jest bezpieczna i pochodzi z zaufanego źródła. Ponadto przesyła również tożsamość początkowego elementu wywołującego wewnątrz tokenu zabezpieczającego Username . W takim przypadku tylko początkowa nazwa użytkownika wywołującego jest przesyłana do usługi zaplecza, hasło nie jest uwzględniane w komunikacie. Dzieje się tak, ponieważ usługa zaplecza ufa usłudze fasady w celu uwierzytelnienia elementu wywołującego przed przekazaniem żądania do niego. Ponieważ usługa fasady uwierzytelnia się w usłudze zaplecza, usługa zaplecza może ufać informacjom zawartym w przesłanym dalej żądaniu.

Poniżej przedstawiono konfigurację powiązania dla tej ścieżki komunikacji.

<bindings>
  <customBinding>
    <binding name="ClientBinding">
      <security authenticationMode="UserNameOverTransport"/>
      <windowsStreamSecurity/>
      <tcpTransport/>
    </binding>
  </customBinding>
</bindings>

Element <powiązania zabezpieczeń> zajmuje się przekazywaniem i wyodrębnianiem nazwy użytkownika początkowego obiektu wywołującego. WindowsStreamSecurity ><i< tcpTransport> zajmują się uwierzytelnianiem usług fasady i zaplecza oraz ochrony komunikatów.

Aby przekazać żądanie, implementacja usługi fasady musi podać nazwę użytkownika początkowego obiektu wywołującego, aby infrastruktura zabezpieczeń WCF mogła umieścić je w przesłanym dalej komunikacie. Początkowa nazwa użytkownika obiektu wywołującego jest udostępniana w implementacji usługi fasady, ustawiając ją we właściwości w ClientCredentials wystąpieniu serwera proxy klienta, którego usługa fasady używa do komunikowania się z usługą zaplecza.

Poniższy kod pokazuje, jak GetCallerIdentity metoda jest implementowana w usłudze fasady. Inne metody używają tego samego wzorca.

public string GetCallerIdentity()
{
    CalculatorClient client = new CalculatorClient();
    client.ClientCredentials.UserName.UserName = ServiceSecurityContext.Current.PrimaryIdentity.Name;
    string result = client.GetCallerIdentity();
    client.Close();
    return result;
}

Jak pokazano w poprzednim kodzie, hasło nie jest ustawione we ClientCredentials właściwości , tylko nazwa użytkownika jest ustawiona. Infrastruktura zabezpieczeń WCF tworzy token zabezpieczający nazwy użytkownika bez hasła w tym przypadku, co jest dokładnie wymagane w tym scenariuszu.

W usłudze zaplecza należy uwierzytelnić informacje zawarte w tokenie zabezpieczającym nazwy użytkownika. Domyślnie zabezpieczenia programu WCF próbują zamapować użytkownika na konto systemu Windows przy użyciu podanego hasła. W takim przypadku nie podano hasła, a usługa zaplecza nie jest wymagana do uwierzytelnienia nazwy użytkownika, ponieważ uwierzytelnianie zostało już wykonane przez usługę fasady. Aby zaimplementować tę funkcję w programie WCF, jest udostępniany niestandardowy UserNamePasswordValidator , który wymusza tylko, że nazwa użytkownika jest określona w tokenie i nie wykonuje dodatkowego uwierzytelniania.

public class MyUserNamePasswordValidator : UserNamePasswordValidator
{
    public override void Validate(string userName, string password)
    {
        // Ignore the password because it is empty,
        // we trust the facade service to authenticate the client.
        // Accept the username information here so that the
        // application gets access to it.
        if (null == userName)
        {
            Console.WriteLine("Invalid username");
            throw new
             SecurityTokenValidationException("Invalid username");
        }
    }
}

Niestandardowy moduł sprawdzania poprawności jest skonfigurowany do użycia wewnątrz serviceCredentials zachowania w pliku konfiguracji usługi fasady.

<behaviors>
  <serviceBehaviors>
    <behavior name="BackendServiceBehavior">
      <serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom"
           customUserNamePasswordValidatorType=
          "Microsoft.ServiceModel.Samples.MyUserNamePasswordValidator,
           BackendService"/>
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>

Aby wyodrębnić informacje o nazwie użytkownika i informacje o zaufanym koncie usługi fasady, implementacja usługi zaplecza ServiceSecurityContext używa klasy . Poniższy kod pokazuje, jak GetCallerIdentity metoda jest implementowana.

public string GetCallerIdentity()
{
    // Facade service is authenticated using Windows authentication.
    //Its identity is accessible.
    // On ServiceSecurityContext.Current.WindowsIdentity.
    string facadeServiceIdentityName =
          ServiceSecurityContext.Current.WindowsIdentity.Name;

    // The client name is transmitted using Username authentication on
    //the message level without the password
    // using a supporting encrypted UserNameToken.
    // Claims extracted from this supporting token are available in
    // ServiceSecurityContext.Current.AuthorizationContext.ClaimSets
    // collection.
    string clientName = null;
    foreach (ClaimSet claimSet in
        ServiceSecurityContext.Current.AuthorizationContext.ClaimSets)
    {
        foreach (Claim claim in claimSet)
        {
            if (claim.ClaimType == ClaimTypes.Name &&
                                   claim.Right == Rights.Identity)
            {
                clientName = (string)claim.Resource;
                break;
            }
        }
    }
    if (clientName == null)
    {
        // In case there was no UserNameToken attached to the request.
        // In the real world implementation the service should reject
        // this request.
        return "Anonymous caller via " + facadeServiceIdentityName;
    }

    return clientName + " via " + facadeServiceIdentityName;
}

Informacje o koncie usługi fasady są wyodrębniane przy użyciu ServiceSecurityContext.Current.WindowsIdentity właściwości . Aby uzyskać dostęp do informacji na temat początkowego obiektu wywołującego, usługa zaplecza ServiceSecurityContext.Current.AuthorizationContext.ClaimSets używa właściwości . Szuka oświadczenia Identity o typie Name. To oświadczenie jest generowane automatycznie przez infrastrukturę zabezpieczeń WCF na podstawie informacji zawartych w tokenie zabezpieczającym Username .

Uruchamianie przykładowej aplikacji

Po uruchomieniu przykładu żądania operacji i odpowiedzi są wyświetlane w oknie konsoli klienta. Naciśnij klawisz ENTER w oknie klienta, aby zamknąć klienta. Możesz nacisnąć klawisz ENTER w oknach konsoli usługi zaplecza i fasady, aby zamknąć usługi.

Username authentication required.
Provide a valid machine or domain ac
   Enter username:
user
   Enter password:
****
user via MyMachine\testaccount
Add(100,15.99) = 115.99
Subtract(145,76.54) = 68.46
Multiply(9,81.25) = 731.25
Divide(22,7) = 3.14285714285714

Press <ENTER> to terminate client.

Plik wsadowy Setup.bat dołączony do przykładowego scenariusza zaufanej fasady umożliwia skonfigurowanie serwera z odpowiednim certyfikatem w celu uruchomienia usługi fasady, która wymaga zabezpieczeń opartych na certyfikatach w celu uwierzytelnienia się na kliencie. Aby uzyskać szczegółowe informacje, zobacz procedurę konfiguracji na końcu tego tematu.

Poniżej przedstawiono krótkie omówienie różnych sekcji plików wsadowych.

  • Tworzenie certyfikatu serwera.

    Następujące wiersze z pliku wsadowego Setup.bat tworzą certyfikat serwera do użycia.

    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
    

    Zmienna %SERVER_NAME% określa nazwę serwera — wartość domyślna to localhost. Certyfikat jest przechowywany w magazynie LocalMachine.

  • Zainstalowanie certyfikatu usługi fasady w zaufanym magazynie certyfikatów klienta.

    Poniższy wiersz kopiuje certyfikat usługi fasady do magazynu zaufanych osób klienta. Ten krok jest wymagany, ponieważ certyfikaty generowane przez Makecert.exe nie są niejawnie zaufane przez system kliencki. Jeśli masz już certyfikat, który jest zakorzeniony w zaufanym certyfikacie głównym klienta — na przykład certyfikat wystawiony przez firmę Microsoft — ten krok wypełniania magazynu certyfikatów klienta przy użyciu certyfikatu serwera nie jest wymagany.

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

Aby skonfigurować, skompilować i uruchomić przykład

  1. Upewnij się, że wykonano procedurę instalacji jednorazowej dla przykładów programu Windows Communication Foundation.

  2. Aby skompilować wersję rozwiązania w języku C# lub Visual Basic .NET, postępuj zgodnie z instrukcjami w temacie Building the Windows Communication Foundation Samples (Tworzenie przykładów programu Windows Communication Foundation).

Aby uruchomić przykład na tej samej maszynie

  1. Upewnij się, że ścieżka zawiera folder, w którym znajduje się Makecert.exe.

  2. Uruchom Setup.bat z folderu instalacji przykładowej. Spowoduje to zainstalowanie wszystkich certyfikatów wymaganych do uruchomienia przykładu.

  3. Uruchom BackendService.exe z katalogu \BackendService\bin w osobnym oknie konsoli

  4. Uruchom FacadeService.exe z katalogu \Service\bin w osobnym oknie konsoli

  5. Uruchom Client.exe z \client\bin. Działanie klienta jest wyświetlane w aplikacji konsolowej klienta.

  6. Jeśli klient i usługa nie mogą się komunikować, zobacz Rozwiązywanie problemów Wskazówki dla przykładów programu WCF.

Aby wyczyścić po próbce

  1. Uruchom Cleanup.bat w folderze samples po zakończeniu uruchamiania przykładu.