Udostępnij za pośrednictwem


Zaufana usługa fasadowa

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 interfejsu kalkulatora

  • Usługa zaplecza kalkulatora

Serwis fasadowy jest odpowiedzialny 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 serwis fasadowy zawiera informacje o tożsamości dzwoniącego, dzięki czemu serwis zaplecza może używać tych informacji w swoim przetwarzaniu. Tożsamość osoby wywołującej jest przesyłana przy użyciu tokenu zabezpieczeń 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 pośredniczącej w celu uwierzytelnienia wywoływacza. W związku z tym usługa zaplecza nie uwierzytelnia ponownie wywołującego; używa informacji o tożsamości dostarczonych przez serwis fasadowy 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 tej usługi.

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 wykorzystuje ścieżkę komunikacji do usługi fasady przy użyciu typu poświadczeń klienta wsHttpBinding, UserName. 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 fasadowa uwierzytelnia wywołującego 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 walidator jest skonfigurowany do użycia wewnątrz zachowania serviceCredentials w pliku konfiguracji usługi façady. 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 fasadowa do komunikacji z usługą zaplecza wykorzystuje ścieżkę z elementem customBinding, która składa się z kilku elementów powiązania. To powiązanie osiąga dwa cele. 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ść pierwotnego rozmówcy 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, że uwierzytelni wywołującego przed przekazaniem jej żądania. Ponieważ usługa fasady uwierzytelnia się w usłudze zaplecza, usługa zaplecza może ufać informacjom zawartym w przekazanym żą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 wywołującego. WindowsStreamSecurity<> i <tcpTransport> zajmują się uwierzytelnianiem usług fasady i zaplecza oraz ochroną komunikatów.

Aby przekazać żądanie, implementacja usługi fasady musi podać nazwę użytkownika początkowego wywołującego, aby infrastruktura zabezpieczeń WCF mogła umieścić ją w przekazanej dalej wiadomości. Nazwa użytkownika początkowego wywołującego jest udostępniana w implementacji usługi fasadowej, ustawiając ją we właściwości instancji serwera proxy klienta ClientCredentials, którą usługa fasadowa używa do komunikowania się z usługą zaplecza.

Poniższy kod pokazuje, jak metoda GetCallerIdentity jest implementowana w usłudze fasadowej. 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 właściwości ClientCredentials, ustawiona jest jedynie nazwa użytkownika. 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 back-end należy uwierzytelnić informacje zawarte w tokenie zabezpieczającym dla 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 walidator jest skonfigurowany do użycia wewnątrz zachowania serviceCredentials w pliku konfiguracji usługi façady.

<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 oraz o zaufanym koncie usługi fasady, implementacja usługi zaplecza używa klasy ServiceSecurityContext. 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 fasadowej są wyodrębniane przy użyciu właściwości ServiceSecurityContext.Current.WindowsIdentity. Aby uzyskać dostęp do informacji o początkowym wywołującym, usługa zaplecza używa właściwości ServiceSecurityContext.Current.AuthorizationContext.ClaimSets. Poszukuje żądania Identity z typem Name. To oświadczenie jest generowane automatycznie przez infrastrukturę zabezpieczeń WCF na podstawie informacji zawartych w tokenie zabezpieczającym Username .

Uruchamianie przykładu

Po uruchomieniu przykładu żądania operacji i odpowiedzi są wyświetlane w oknie konsoli klienta. Naciśnij ENTER w oknie klienta, aby zamknąć klienta. Możesz nacisnąć ENTER w konsolach usług fasady i zaplecza, aby zamknąć te 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 Trusted Facade umożliwia skonfigurowanie serwera przy użyciu odpowiedniego certyfikatu w celu uruchomienia usługi fasady, która wymaga zabezpieczeń opartych na certyfikatach w celu uwierzytelnienia się względem klienta. 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 serwisu fasadowego do magazynu zaufanych certyfikatów klienta. Ten krok jest wymagany, ponieważ certyfikaty generowane przez Makecert.exe nie są automatycznie uznawane za zaufane przez system klienta. 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ładowy program

  1. Upewnij się, że wykonano procedurę instalacji One-Time 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 Kompilowanie przykładów 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. To instaluje wszystkie certyfikaty wymagane do uruchomienia próbki.

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

  4. Uruchom FacadeService.exe z katalogu \FacadeService\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ć, sprawdź sekcję „Wskazówki dotyczące rozwiązywania problemów z przykładami programu WCF”.

Aby posprzątać po próbie

  1. Uruchom Cleanup.bat w folderze próbek po zakończeniu uruchamiania próbki.