Obsługa Spring Security w Spring Cloud Azure

W tym artykule opisano sposób, w jaki platforma Spring Cloud i usługa Spring Security mogą być używane razem.

Usługa Spring Security z identyfikatorem Entra firmy Microsoft

Podczas tworzenia aplikacji internetowej tożsamość i zarządzanie dostępem zawsze będą podstawowymi elementami.

Platforma Azure oferuje doskonałą platformę do demokratyzacji rozwoju aplikacji, ponieważ nie tylko oferuje usługę tożsamości w chmurze, ale także głęboką integrację z resztą ekosystemu platformy Azure.

Usługa Spring Security ułatwia zabezpieczanie aplikacji opartych na platformie Spring za pomocą zaawansowanych abstrakcji i rozszerzalnych interfejsów. Jednak choć framework Spring jest bardzo potężny, nie jest dostosowany do konkretnego dostawcy tożsamości.

spring-cloud-azure-starter-active-directory zapewnia najlepszy sposób na połączenie aplikacji internetowej z dzierżawą Microsoft Entra ID (w skrócie Microsoft Entra ID) oraz ochronę serwera zasobów przy użyciu Microsoft Entra ID. Używa protokołu Oauth 2.0 do ochrony aplikacji internetowych i serwerów zasobów.

Uzyskiwanie dostępu do aplikacji internetowej

Ten scenariusz wykorzystuje przepływ kodu autoryzacyjnego OAuth 2.0, aby zalogować użytkownika za pomocą konta Microsoft.

Diagram systemowy

Diagram systemu dla autonomicznej aplikacji internetowej.

Tworzenie wymaganych zasobów na platformie Azure

  1. Przeczytaj Szybki start: rejestrowanie aplikacji za pomocą platformy tożsamości firmy Microsoft.

  2. Utwórz rejestrację aplikacji. Pobierz AZURE_TENANT_ID, AZURE_CLIENT_IDi AZURE_CLIENT_SECRET.

  3. Ustaw redirect URI na APPLICATION_BASE_URI/login/oauth2/code/ — na przykład http://localhost:8080/login/oauth2/code/. Wymagany jest końcowy znacznik /.

Dodawanie wymaganych zależności

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
</dependencies>

Dodawanie wymaganych właściwości

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: <tenant>
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}

Uwaga

Dozwolone wartości dla tenant-id to: common, organizations, consumerslub identyfikator dzierżawy. Aby uzyskać więcej informacji na temat tych wartości, zobacz sekcję Użyto niewłaściwego punktu końcowego (konta osobiste i organizacyjne) w artykule Błąd AADSTS50020 — konto użytkownika od dostawcy tożsamości nie istnieje w dzierżawie. Aby uzyskać informacje na temat konwersji aplikacji z jedną dzierżawą na aplikację wielodzierżawną, zobacz Konwertowanie aplikacji z jedną dzierżawą na aplikację wielodzierżawną w usłudze Microsoft Entra ID.

Teraz uruchom aplikację i uzyskaj dostęp do aplikacji za pośrednictwem przeglądarki. Nastąpi przekierowanie do strony logowania firmy Microsoft.

Zaawansowane użycie

Dodawanie dodatkowych konfiguracji zabezpieczeń
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableMethodSecurity
public class AadOAuth2LoginSecurityConfig {

   /**
    * Add configuration logic as needed.
    */
   @Bean
   SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
       http.with(AadWebApplicationHttpSecurityConfigurer.aadWebApplication(), Customizer.withDefaults())
           .authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated());
           // Do some custom configuration.
       return http.build();
   }
}
Autoryzowanie dostępu według ról aplikacji

Utwórz wymagane zasoby na platformie Azure:

Uwaga

Jeśli chcesz użyć kontroli dostępu opartej na rolach aplikacji, nie możesz umieścić nazw grup w oświadczeniu role. Aby uzyskać więcej informacji, zobacz sekcję Configuring groups optional claims (Konfigurowanie opcjonalnych oświadczeń grup) sekcji Provide optional claims to your app(Dostarczanie opcjonalnych oświadczeń do aplikacji).

Chroń określoną metodę.

class Demo {
   @GetMapping("Admin")
   @ResponseBody
   @PreAuthorize("hasAuthority('APPROLE_Admin')")
   public String admin() {
       return "Admin message";
   }
}
Autoryzowanie dostępu według nazwy grupy lub identyfikatora grupy

Dodaj powiązane właściwości konfiguracji.

spring:
 cloud:
   azure:
     active-directory:
       enabled: true
       user-group:
         allowed-group-names: group1_name_1, group2_name_2
         # 1. If allowed-group-ids == all, then all group ID will take effect.
         # 2. If "all" is used, we should not configure other group ids.
         # 3. "all" is only supported for allowed-group-ids, not supported for allowed-group-names.
         allowed-group-ids: group_id_1, group_id_2

Chroń określoną metodę.

@Controller
public class RoleController {
   @GetMapping("group1")
   @ResponseBody
   @PreAuthorize("hasRole('ROLE_group1')")
   public String group1() {
       return "group1 message";
   }

   @GetMapping("group2")
   @ResponseBody
   @PreAuthorize("hasRole('ROLE_group2')")
   public String group2() {
       return "group2 message";
   }

   @GetMapping("group1Id")
   @ResponseBody
   @PreAuthorize("hasRole('ROLE_<group1-id>')")
   public String group1Id() {
       return "group1Id message";
   }

   @GetMapping("group2Id")
   @ResponseBody
   @PreAuthorize("hasRole('ROLE_<group2-id>')")
   public String group2Id() {
       return "group2Id message";
   }
}
Korzystanie z krajowej platformy Azure zamiast globalnej platformy Azure

Teraz z wyjątkiem globalnej chmury platformy Azure identyfikator Entra firmy Microsoft jest wdrażany w następujących chmurach krajowych:

  • Azure Government

  • Azure (Chiny) — 21Vianet

  • Azure Niemcy

Oto przykład z użyciem usługi Azure (Chiny) — 21Vianet.

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        base-uri: https://login.partner.microsoftonline.cn
        graph-base-uri: https://microsoftgraph.chinacloudapi.cn

Aby uzyskać więcej informacji, zobacz Wdrożenia chmury krajowej.

Skonfiguruj szablon identyfikatora URI przekierowania

Deweloperzy mogą dostosować adres URI przekierowania.

Diagram systemu dla identyfikatorów URI przekierowania.

Dodaj właściwości redirect-uri-template w pliku application.yml.

spring:
 cloud:
   azure:
     active-directory:
       enabled: true
       redirect-uri-template: ${REDIRECT-URI-TEMPLATE}

Zaktualizuj redirect-uri w portalu Azure.

Skonfiguruj szablon URI przekierowania.

Po ustawieniu redirect-uri-templatemusimy zaktualizować konstruktora zabezpieczeń:

@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableMethodSecurity
public class AadOAuth2LoginSecurityConfig {

    /**
     * Add configuration logic as needed.
     */
    @Bean
    public SecurityFilterChain htmlFilterChain(HttpSecurity http) throws Exception {
        // @formatter:off
        http.with(AadWebApplicationHttpSecurityConfigurer.aadWebApplication(), Customizer.withDefaults())
            .oauth2Login(login -> login.loginProcessingUrl("${REDIRECT-URI-TEMPLATE}"))
            .authorizeHttpRequests(auth -> auth.anyRequest().authenticated());
        // @formatter:on
        return http.build();
    }
}

Nawiązywanie połączenia z identyfikatorem Entra firmy Microsoft za pośrednictwem serwera proxy

Aby połączyć usługę Microsoft Entra ID za pośrednictwem serwera proxy, należy podać element bean podobny do pokazanego w poniższym przykładzie:

@Configuration
class DemoConfiguration {
    @Bean
    public RestTemplateCustomizer proxyRestTemplateCustomizer() {
        return (RestTemplate restTemplate) -> {
            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_SERVER_HOST, PROXY_SERVER_PORT));
            SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
            requestFactory.setProxy(proxy);
            restTemplate.setRequestFactory(requestFactory);
        };
    }
}

Próbki

Przykładowy projekt: aad-web-application.

Aplikacja internetowa, która uzyskuje dostęp do serwerów zasobów

Diagram systemowy

Diagram systemu dla aplikacji internetowej, która uzyskuje dostęp do serwerów zasobów.

Tworzenie wymaganych zasobów na platformie Azure

  1. Przeczytaj Szybki start: rejestrowanie aplikacji za pomocą platformy tożsamości firmy Microsoft.

  2. Utwórz rejestrację aplikacji. Pobierz AZURE_TENANT_ID, AZURE_CLIENT_IDi AZURE_CLIENT_SECRET.

  3. Ustaw redirect URI na APPLICATION_BASE_URI/login/oauth2/code/, na przykład http://localhost:8080/login/oauth2/code/. Wymagany jest końcowy znacznik /.

Dodawanie wymaganych zależności

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
</dependencies>

Dodawanie wymaganych właściwości

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: <tenant>
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        authorization-clients:
          graph:
            scopes: https://graph.microsoft.com/Analytics.Read, email

Uwaga

Dozwolone wartości dla tenant-id to: common, organizations, consumerslub identyfikator dzierżawy. Aby uzyskać więcej informacji na temat tych wartości, zobacz sekcję Użyto niewłaściwego punktu końcowego (konta osobiste i organizacyjne) w artykule Błąd AADSTS50020 — konto użytkownika od dostawcy tożsamości nie istnieje w dzierżawie. Aby uzyskać informacje na temat konwersji aplikacji z jedną dzierżawą na aplikację wielodzierżawną, zobacz Konwertowanie aplikacji z jedną dzierżawą na aplikację wielodzierżawną w usłudze Microsoft Entra ID.

W tym miejscu graph jest nazwą OAuth2AuthorizedClient, scopes oznacza zakresy wymagane do wyrażenia zgody podczas logowania.

Użyj OAuth2AuthorizedClient w swojej aplikacji

public class Demo {
    @GetMapping("/graph")
    @ResponseBody
    public String graph(
    @RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient graphClient) {
        // toJsonString() is just a demo.
        // oAuth2AuthorizedClient contains access_token. We can use this access_token to access resource server.
        return toJsonString(graphClient);
    }
}

Teraz uruchom aplikację i uzyskaj dostęp do aplikacji w przeglądarce. Następnie nastąpi przekierowanie do strony logowania firmy Microsoft.

Zaawansowane użycie

Przepływ poświadczeń klienta

Domyślny przepływ to przepływ kodu autoryzacji, jeśli chcesz użyć przepływu poświadczeń klienta , możesz skonfigurować w następujący sposób:

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: <tenant>
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        authorization-clients:
          graph:
            authorization-grant-type: client_credentials # Change type to client_credentials
            scopes: https://graph.microsoft.com/Analytics.Read, email

Uwaga

Dozwolone wartości dla tenant-id to: common, organizations, consumerslub identyfikator dzierżawy. Aby uzyskać więcej informacji na temat tych wartości, zobacz sekcję Użyto niewłaściwego punktu końcowego (konta osobiste i organizacyjne) w artykule Błąd AADSTS50020 — konto użytkownika od dostawcy tożsamości nie istnieje w dzierżawie. Aby uzyskać informacje na temat konwersji aplikacji z jedną dzierżawą na aplikację wielodzierżawną, zobacz Konwertowanie aplikacji z jedną dzierżawą na aplikację wielodzierżawną w usłudze Microsoft Entra ID.

Uzyskiwanie dostępu do wielu serwerów zasobów

W jednej aplikacji internetowej można uzyskać dostęp do wielu serwerów zasobów, konfigurując w następujący sposób:

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: <tenant>
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        authorization-clients:
          resource-server-1:
            scopes: # Scopes for resource-server-1
          resource-server-2:
            scopes: # Scopes for resource-server-2

Uwaga

Dozwolone wartości dla tenant-id to: common, organizations, consumerslub identyfikator dzierżawy. Aby uzyskać więcej informacji na temat tych wartości, zobacz sekcję Użyto niewłaściwego punktu końcowego (konta osobiste i organizacyjne) w artykule Błąd AADSTS50020 — konto użytkownika od dostawcy tożsamości nie istnieje w dzierżawie. Aby uzyskać informacje na temat konwersji aplikacji z jedną dzierżawą na aplikację wielodzierżawną, zobacz Konwertowanie aplikacji z jedną dzierżawą na aplikację wielodzierżawną w usłudze Microsoft Entra ID.

Następnie możesz użyć OAuth2AuthorizedClient w aplikacji w następujący sposób

public class Demo {
    @GetMapping("/resource-server-1")
    @ResponseBody
    public String graph1(
    @RegisteredOAuth2AuthorizedClient("resource-server-1") OAuth2AuthorizedClient client) {
        return callResourceServer1(client);
    }

    @GetMapping("/resource-server-2")
    @ResponseBody
    public String graph2(
    @RegisteredOAuth2AuthorizedClient("resource-server-2") OAuth2AuthorizedClient client) {
        return callResourceServer2(client);
    }
}

Próbki

Przykładowy projekt: aad-web-application.

Uzyskiwanie dostępu do serwera zasobów

Ten scenariusz nie obsługuje logowania, po prostu chroni serwer, sprawdzając token dostępu. Jeśli token dostępu jest prawidłowy, serwer obsługuje żądanie.

Diagram systemowy

Diagram systemu na potrzeby użycia autonomicznego serwera zasobów.

Tworzenie wymaganych zasobów na platformie Azure

  1. Przeczytaj Szybki start: rejestrowanie aplikacji za pomocą platformy tożsamości firmy Microsoft.

  2. Utwórz rejestrację aplikacji. Pobierz AZURE_CLIENT_ID.

  3. Przeczytaj Szybki start: konfigurowanie aplikacji w celu uwidocznienia internetowego interfejsu API.

  4. Udostępnij internetowy interfejs API o zakresie o nazwie Scope-1.

Dodawanie wymaganych zależności

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>
</dependencies>

Dodawanie wymaganych właściwości

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        credential:
          client-id: ${AZURE_CLIENT_ID}

Teraz uruchom aplikację i uzyskaj dostęp do internetowego interfejsu API aplikacji.

  1. Otrzymasz kod 401 bez tokenu dostępu.

  2. Uzyskiwanie dostępu do aplikacji przy użyciu tokenu dostępu. Następujące oświadczenia w tokenie dostępu zostaną zweryfikowane:

    • iss: token dostępu musi być wystawiony przez identyfikator Entra firmy Microsoft.

    • nbf: bieżąca godzina nie może być wcześniejsza niż nbf.

    • exp: bieżąca godzina nie może być późniejsza niż exp.

    • aud: Jeśli skonfigurowano spring.cloud.azure.active-directory.credential.client-id lub spring.cloud.azure.active-directory.credential.app-id-uri, wartość audience musi być równa skonfigurowanemu client-id lub app-id-uri. Jeśli te dwie właściwości nie są skonfigurowane, to oświadczenie nie zostanie zweryfikowane.

Aby uzyskać więcej informacji na temat tokenu dostępu, zobacz dokumentację firmy Microsoft dotyczącą tokenów dostępu platformy tożsamości Microsoft.

Zaawansowane użycie

Dodawanie dodatkowych konfiguracji zabezpieczeń
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableMethodSecurity
public class AadOAuth2ResourceServerSecurityConfig {

    /**
     * Add configuration logic as needed.
     */
    @Bean
    public SecurityFilterChain htmlFilterChain(HttpSecurity http) throws Exception {
        // @formatter:off
        http.with(AadResourceServerHttpSecurityConfigurer.aadResourceServer(), Customizer.withDefaults())
            .authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated());
        // @formatter:on
        return http.build();
    }
}
Weryfikowanie uprawnień według zakresów
  1. Tworzenie wymaganych zasobów na platformie Azure.

  2. Chroń określoną metodę.

    class Demo {
        @GetMapping("scope1")
        @ResponseBody
        @PreAuthorize("hasAuthority('SCOPE_Scope1')")
        public String scope1() {
            return "Congratulations, you can access `scope1` endpoint.";
        }
    }
    

Dzięki temu podczas uzyskiwania dostępu do punktu końcowego /scope1 zostaną zweryfikowane następujące claimy w tokenie dostępu:

  • scp: wartość musi zawierać Scope1.
Weryfikowanie uprawnień według ról aplikacji
  1. Tworzenie wymaganych zasobów na platformie Azure.

  2. Chroń określoną metodę.

    class Demo {
        @GetMapping("app-role1")
        @ResponseBody
        @PreAuthorize("hasAuthority('APPROLE_AppRole1')")
        public String appRole1() {
            return "Congratulations, you can access `app-role1` endpoint.";
        }
    }
    

Dzięki temu podczas uzyskiwania dostępu do punktu końcowego /app-role1 zostaną zweryfikowane następujące claimy w tokenie dostępu:

  • roles: wartość musi zawierać AppRole1.
Korzystanie z uwierzytelniania klienta JWT

Aby użyć tokenu internetowego JSON (JWT) do uwierzytelniania klienta, wykonaj następujące kroki:

  1. Zobacz sekcję Register your certificate with Platforma tożsamości Microsoft (Rejestrowanie certyfikatu za pomocą platformy tożsamości firmy Microsoft) sekcji Poświadczenia certyfikatu uwierzytelniania aplikacji platformy tożsamości firmy Microsoft.
  2. Przekaż certyfikat .pem do aplikacji zarejestrowanej w witrynie Azure Portal.
  3. Skonfiguruj ścieżkę do certyfikatu oraz hasło certyfikatu .PFX lub .P12.
  4. Dodaj do klienta właściwość konfiguracyjną spring.cloud.azure.active-directory.authorization-clients.azure.client-authentication-method=private_key_jwt, aby był uwierzytelniany przy użyciu uwierzytelniania klienta JWT.

Poniższy przykładowy plik konfiguracji jest przeznaczony dla scenariusza aplikacji internetowej. Informacje o certyfikacie są konfigurowane we właściwościach globalnych.

spring:
  cloud:
    azure:
      credential:
        client-id: ${AZURE_CLIENT_ID}
        client-certificate-path: ${AZURE_CERTIFICATE_PATH}
        client-certificate-password: ${AZURE_CERTIFICATE_PASSWORD}
      profile:
        tenant-id: <tenant>
      active-directory:
        enabled: true
        user-group:
          allowed-group-names: group1,group2
          allowed-group-ids: <group1-id>,<group2-id>
        post-logout-redirect-uri: http://localhost:8080
        authorization-clients:
          azure:
            client-authentication-method: private_key_jwt
          arm:
            client-authentication-method: private_key_jwt
            scopes: https://management.core.windows.net/user_impersonation
          graph:
            client-authentication-method: private_key_jwt
            scopes:
              - https://graph.microsoft.com/User.Read
              - https://graph.microsoft.com/Directory.Read.All
          webapiA:
            client-authentication-method: private_key_jwt
            scopes:
              - ${WEB_API_A_APP_ID_URL}/Obo.WebApiA.ExampleScope
          webapiB:
            client-authentication-method: private_key_jwt
            scopes:
              - ${WEB_API_B_APP_ID_URL}/.default
            authorization-grant-type: client_credentials

Uwaga

Dozwolone wartości dla tenant-id to: common, organizations, consumerslub identyfikator dzierżawy. Aby uzyskać więcej informacji na temat tych wartości, zobacz sekcję Użyto niewłaściwego punktu końcowego (konta osobiste i organizacyjne) w artykule Błąd AADSTS50020 — konto użytkownika od dostawcy tożsamości nie istnieje w dzierżawie. Aby uzyskać informacje na temat konwersji aplikacji z jedną dzierżawą na aplikację wielodzierżawną, zobacz Konwertowanie aplikacji z jedną dzierżawą na aplikację wielodzierżawną w usłudze Microsoft Entra ID.

Informacje o certyfikacie można również skonfigurować we właściwościach usługi active-directory, jak pokazano w tym przykładzie:

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-certificate-path: ${AZURE_CERTIFICATE_PATH}
          client-certificate-password: ${AZURE_CERTIFICATE_PASSWORD}
        profile:
          tenant-id: <tenant>
        user-group:
          allowed-group-names: group1,group2
          allowed-group-ids: <group1-id>,<group2-id>
        post-logout-redirect-uri: http://localhost:8080
        authorization-clients:
          azure:
            client-authentication-method: private_key_jwt
          arm:
            client-authentication-method: private_key_jwt
            scopes: https://management.core.windows.net/user_impersonation
          graph:
            client-authentication-method: private_key_jwt
            scopes:
              - https://graph.microsoft.com/User.Read
              - https://graph.microsoft.com/Directory.Read.All
          webapiA:
            client-authentication-method: private_key_jwt
            scopes:
              - ${WEB_API_A_APP_ID_URL}/Obo.WebApiA.ExampleScope
          webapiB:
            client-authentication-method: private_key_jwt
            scopes:
              - ${WEB_API_B_APP_ID_URL}/.default
            authorization-grant-type: client_credentials

Uwaga

Dozwolone wartości dla tenant-id to: common, organizations, consumerslub identyfikator dzierżawy. Aby uzyskać więcej informacji na temat tych wartości, zobacz sekcję Użyto niewłaściwego punktu końcowego (konta osobiste i organizacyjne) w artykule Błąd AADSTS50020 — konto użytkownika od dostawcy tożsamości nie istnieje w dzierżawie. Aby uzyskać informacje na temat konwersji aplikacji z jedną dzierżawą na aplikację wielodzierżawną, zobacz Konwertowanie aplikacji z jedną dzierżawą na aplikację wielodzierżawną w usłudze Microsoft Entra ID.

Nawiązywanie połączenia z identyfikatorem Entra firmy Microsoft za pośrednictwem serwera proxy

Aby połączyć się z usługą Microsoft Entra ID za pośrednictwem serwera proxy, zdefiniuj bean RestTemplateCustomizer. Aby uzyskać więcej informacji, zobacz sekcję Connecting to Microsoft Entra ID via proxy (Łączenie z firmą Microsoft Entra ID za pośrednictwem serwera proxy).

Próbki

Przykładowy projekt: aad-resource-server.

Serwer zasobów odwiedzający inne serwery zasobów

Diagram systemowy

Diagram systemu dla serwera zasobów odwiedzającego inne serwery zasobów.

Tworzenie wymaganych zasobów na platformie Azure

  1. Przeczytaj Szybki start: rejestrowanie aplikacji za pomocą platformy tożsamości firmy Microsoft.

  2. Utwórz rejestrację aplikacji. Pobierz AZURE_TENANT_ID, AZURE_CLIENT_IDi AZURE_CLIENT_SECRET.

Dodawanie wymaganych zależności

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
</dependencies>

Dodawanie wymaganych właściwości

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: <tenant>
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        authorization-clients:
          graph:
            scopes:
              - https://graph.microsoft.com/User.Read

Uwaga

Dozwolone wartości dla tenant-id to: common, organizations, consumerslub identyfikator dzierżawy. Aby uzyskać więcej informacji na temat tych wartości, zobacz sekcję Użyto niewłaściwego punktu końcowego (konta osobiste i organizacyjne) w artykule Błąd AADSTS50020 — konto użytkownika od dostawcy tożsamości nie istnieje w dzierżawie. Aby uzyskać informacje na temat konwersji aplikacji z jedną dzierżawą na aplikację wielodzierżawną, zobacz Konwertowanie aplikacji z jedną dzierżawą na aplikację wielodzierżawną w usłudze Microsoft Entra ID.

Użyj OAuth2AuthorizedClient w swojej aplikacji

public class SampleController {
    @GetMapping("call-graph")
    public String callGraph(@RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient graph) {
        return callMicrosoftGraphMeEndpoint(graph);
    }
}

Próbki

Przykładowy projekt: aad-resource-server-obo.

Aplikacja internetowa i serwer zasobów w jednej aplikacji

Tworzenie wymaganych zasobów na platformie Azure

  1. Przeczytaj Szybki start: rejestrowanie aplikacji za pomocą platformy tożsamości firmy Microsoft.

  2. Utwórz rejestrację aplikacji. Pobierz AZURE_TENANT_ID, AZURE_CLIENT_IDi AZURE_CLIENT_SECRET.

Dodawanie wymaganych zależności

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
</dependencies>

Dodawanie wymaganych właściwości

Ustaw właściwość spring.cloud.azure.active-directory.application-type na web_application_and_resource_serveri określ typ autoryzacji dla każdego klienta autoryzacji.

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: <tenant>
        credential:
          client-id: ${AZURE_CLIENT_ID}
          client-secret: ${AZURE_CLIENT_SECRET}
        app-id-uri: ${WEB_API_ID_URI}
        application-type: web_application_and_resource_server  # This is required.
        authorization-clients:
          graph:
            authorizationGrantType: authorization_code # This is required.
            scopes:
              - https://graph.microsoft.com/User.Read
              - https://graph.microsoft.com/Directory.Read.All

Uwaga

Dozwolone wartości dla tenant-id to: common, organizations, consumerslub identyfikator dzierżawy. Aby uzyskać więcej informacji na temat tych wartości, zobacz sekcję Użyto niewłaściwego punktu końcowego (konta osobiste i organizacyjne) w artykule Błąd AADSTS50020 — konto użytkownika od dostawcy tożsamości nie istnieje w dzierżawie. Aby uzyskać informacje na temat konwersji aplikacji z jedną dzierżawą na aplikację wielodzierżawną, zobacz Konwertowanie aplikacji z jedną dzierżawą na aplikację wielodzierżawną w usłudze Microsoft Entra ID.

Definiowanie elementu SecurityFilterChain

Skonfiguruj wiele wystąpień SecurityFilterChain. AadWebApplicationAndResourceServerConfig zawiera dwie konfiguracje łańcucha filtrów zabezpieczeń dla serwera zasobów i aplikacji internetowej.

@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableMethodSecurity
public class AadWebApplicationAndResourceServerConfig {

    @Bean
    @Order(1)
    public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
        http.with(AadResourceServerHttpSecurityConfigurer.aadResourceServer(), Customizer.withDefaults())
            // All the paths that match `/api/**`(configurable) work as the resource server. Other paths work as the web application.
            .securityMatcher("/api/**")
            .authorizeHttpRequests(auth -> auth.anyRequest().authenticated());
        return http.build();
    }

    @Bean
    public SecurityFilterChain htmlFilterChain(HttpSecurity http) throws Exception {
        // @formatter:off
        http.with(AadWebApplicationHttpSecurityConfigurer.aadWebApplication(), Customizer.withDefaults())
            .authorizeHttpRequests(auth -> auth.requestMatchers("/login").permitAll().anyRequest().authenticated());
        // @formatter:on
        return http.build();
    }
}

Konfiguracja

Konfigurowalne właściwości elementu spring-cloud-azure-starter-active-directory:

Nazwa Opis
spring.cloud.azure.active-directory.app-id-uri Identyfikator URI aplikacji, który może być używany jako roszczenie „aud” w id_token.
spring.cloud.azure.active-directory.application-type Typ aplikacji Microsoft Entra.
spring.cloud.azure.active-directory.authenticate-additional-parameters Dodaj dodatkowe parametry do adresu URL autoryzacji.
spring.cloud.azure.active-directory.authorization-clients Klienci autoryzacji OAuth2.
spring.cloud.azure.active-directory.credential.client-id Identyfikator klienta do użycia podczas przeprowadzania uwierzytelniania jednostki usługi za pomocą platformy Azure.
spring.cloud.azure.active-directory.credential.client-secret Klucz tajny klienta używany podczas przeprowadzania uwierzytelniania jednostki usługi za pomocą platformy Azure.
spring.cloud.azure.active-directory.jwk-set-cache-lifespan Okres ważności buforowanego zestawu JWK przed jego wygaśnięciem; wartość domyślna to 5 minut.
spring.cloud.azure.active-directory.jwk-set-cache-refresh-time Czas odświeżania zestawu JWK przechowywanego w pamięci podręcznej przed jego wygaśnięciem; wartość domyślna to 5 minut.
spring.cloud.azure.active-directory.jwt-connect-timeout Limit czasu połączenia dla wywołania do zdalnego adresu URL JWKSet.
spring.cloud.azure.active-directory.jwt-read-timeout Limit czasu odczytu dla wywołania do zdalnego adresu URL JWKSet.
spring.cloud.azure.active-directory.jwt-size-limit Maksymalny rozmiar w bajtach wywołania do zdalnego adresu URL JWK Set.
spring.cloud.azure.active-directory.post-logout-redirect-uri URI przekierowania po wylogowaniu.
spring.cloud.azure.active-directory.profile.cloud-type Nazwa chmury platformy Azure do nawiązania połączenia. Obsługiwane typy to: AZURE, AZURE_CHINA, AZURE_GERMANY, AZURE_US_GOVERNMENT, OTHER.
spring.cloud.azure.active-directory.profile.environment Właściwości punktów końcowych usługi Microsoft Entra.
spring.cloud.azure.active-directory.profile.tenant-id Identyfikator dzierżawy platformy Azure. Dozwolone wartości dla tenant-id to: common, organizations, consumerslub identyfikator dzierżawy.
spring.cloud.azure.active-directory.redirect-uri-template Punkt końcowy przekierowania: używany przez serwer autoryzacji do zwracania odpowiedzi zawierających poświadczenia autoryzacji do klienta za pośrednictwem agenta użytkownika-właściciela zasobu. Wartość domyślna to {baseUrl}/login/oauth2/code/.
spring.cloud.azure.active-directory.resource-server.claim-to-authority-prefix-map Skonfiguruj, który claim będzie używany do tworzenia obiektu GrantedAuthority, oraz prefiks wartości ciągu znaków obiektu GrantedAuthority. Wartość domyślna to: "scp" —> "SCOPE_", "roles" —> "APPROLE_".
spring.cloud.azure.active-directory.resource-server.principal-claim-name Skonfiguruj, który atrybut tokenu dostępu ma być zwracany przez metodę AuthenticatedPrincipal#getName. Wartość domyślna to "sub".
spring.cloud.azure.active-directory.session-stateless Jeśli wartość true, aktywuje filtr bezstanowego uwierzytelniania AadAppRoleStatelessAuthenticationFilter. Wartość domyślna to false, która aktywuje filtr AadAuthenticationFilter.
spring.cloud.azure.active-directory.user-group.allowed-group-ids Identyfikatory grup mogą służyć do tworzenia obiektu GrantedAuthority.
spring.cloud.azure.active-directory.user-group.allowed-group-names Nazwy grup mogą służyć do konstruowania aplikacji GrantedAuthority.
spring.cloud.azure.active-directory.user-group.use-transitive-members Jeśli wartość "true", użyj polecenia "v1.0/me/transitiveMemberOf", aby uzyskać członków. W przeciwnym razie użyj „v1.0/me/memberOf”. Wartość domyślna to false.
spring.cloud.azure.active-directory.user-name-attribute Zdecyduj, które oświadczenie ma stanowić nazwę podmiotu.

Oto kilka przykładów dotyczących używania tych właściwości:

Typ aplikacji

Typ aplikacji można wywnioskować z zależności: spring-security-oauth2-client lub spring-security-oauth2-resource-server. Jeśli wywnioskowana wartość nie jest odpowiednią wartością, możesz określić typ aplikacji. Oto tabela prawidłowych wartości i wywnioskowanych wartości:

Typ aplikacji spring-cloud-azure-starter-active-directory:

Ma zależności: spring-security-oauth2-client Ma zależności od: spring-security-oauth2-resource-server Prawidłowe wartości typu aplikacji Wartość wywnioskowana
Tak Nie web_application web_application
Nie Tak resource_server resource_server
Tak Tak web_application, , resource_server, , resource_server_with_oboweb_application_and_resource_server resource_server_with_obo

Spring Security z usługą Azure Active Directory B2C

Azure Active Directory (Azure AD) B2C to usługa zarządzania tożsamościami, która umożliwia dostosowywanie i kontrolowanie sposobu rejestrowania się, logowania i zarządzania profilami klientów podczas korzystania z aplikacji. Usługa Azure AD B2C umożliwia wykonywanie tych akcji przy jednoczesnej ochronie tożsamości klientów.

Konfiguracja zależności

<dependencies>
    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory-b2c</artifactId>
    </dependency>
</dependencies>

Konfiguracja

Konfigurowalne właściwości elementu spring-cloud-azure-starter-active-directory-b2c:

Nazwa Opis
spring.cloud.azure.active-directory.b2c.app-id-uri Identyfikator URI aplikacji, który może być używany w roszczeniu „aud” tokenu.
spring.cloud.azure.active-directory.b2c.authenticate-additional-parameters Dodatkowe parametry uwierzytelniania.
spring.cloud.azure.active-directory.b2c.authorization-clients Określ konfigurację klienta.
spring.cloud.azure.active-directory.b2c.base-uri Bazowy identyfikator URI punktu końcowego usługi Azure AD B2C.
spring.cloud.azure.active-directory.b2c.credential Informacje o poświadczeniach usługi Azure AD B2C.
spring.cloud.azure.active-directory.b2c.jwt-connect-timeout Limit czasu połączenia dla wywołania do zdalnego adresu URL JWKSet.
spring.cloud.azure.active-directory.b2c.jwt-read-timeout Limit czasu odczytu dla wywołania do zdalnego adresu URL JWKSet.
spring.cloud.azure.active-directory.b2c.jwt-size-limit Maksymalny rozmiar w bajtach wywołania do zdalnego adresu URL JWK Set.
spring.cloud.azure.active-directory.b2c.login-flow Określ klucz głównego procesu logowania. Wartość domyślna to sign-up-or-sign-in.
spring.cloud.azure.active-directory.b2c.logout-success-url Adres URL przekierowania po wylogowaniu. Wartość domyślna to http://localhost:8080/login.
spring.cloud.azure.active-directory.b2c.profile Informacje o profilu usługi Azure AD B2C.
spring.cloud.azure.active-directory.b2c.reply-url Adres URL odpowiedzi po otrzymaniu kodu autoryzacji. Wartość domyślna to {baseUrl}/login/oauth2/code/.
spring.cloud.azure.active-directory.b2c.user-flows Przepływy użytkownika.
spring.cloud.azure.active-directory.b2c.user-name-attribute-name Nazwa atrybutu nazwy użytkownika.

Aby uzyskać pełne konfiguracje, sprawdź właściwości konfiguracji platformy Azure Spring Cloud.

Podstawowe użycie

Aplikacja internetowa to dowolna aplikacja oparta na sieci Web, która umożliwia użytkownikowi zalogowanie się za pomocą Microsoft Entra ID, natomiast serwer zasobów po zweryfikowaniu tokenu dostępu access_token uzyskanego z Microsoft Entra ID przyzna albo odmówi dostępu. W tym przewodniku omówimy 4 scenariusze:

  1. Uzyskiwanie dostępu do aplikacji internetowej.

  2. Aplikacja internetowa uzyskuje dostęp do serwerów zasobów.

  3. Uzyskiwanie dostępu do serwera zasobów.

  4. Serwer zasobów uzyskuje dostęp do innych serwerów zasobów.

Użycie 1. Uzyskiwanie dostępu do aplikacji internetowej

Ten scenariusz wykorzystuje przepływ kodu autoryzacyjnego OAuth 2.0 do logowania użytkownika przy użyciu użytkownika usługi Azure AD B2C.

Wybierz usługi Azure AD B2C z menu portalu, wybierz pozycję Aplikacje, a następnie wybierz pozycję Dodaj.

Określ nazwę aplikacji (na przykład ), dodaj dla adresu URL odpowiedzi, zapisz identyfikator aplikacji jako , a następnie wybierz Zapisz.

Wybierz pozycję klucze z aplikacji, wybierz pozycję Wygeneruj klucz, aby wygenerować WEB_APP_AZURE_CLIENT_SECRET, a następnie wybierz pozycję Zapisz.

Wybierz pozycję Przepływy użytkownika po lewej stronie, a następnie wybierz pozycję Nowy przepływ użytkownika.

Wybierz opcje Zarejestruj się lub zaloguj, Edytowanie profilu i Resetowanie hasła, aby odpowiednio utworzyć przepływy użytkowników. Określ przepływ użytkownika Nazwa i atrybuty użytkownika i oświadczenia użytkownika , a następnie wybierz pozycję Utwórz.

Wybierz Uprawnienia interfejsu API>Dodaj uprawnienie>Interfejsy API firmy Microsoft, wybierz Microsoft Graph, wybierz Uprawnienia delegowane, wybierz uprawnienia offline_access i openid, a następnie wybierz Dodaj uprawnienie, aby zakończyć proces.

Udziel zgody administratora na uprawnienia usługi Graph.

Zrzut ekranu portalu Azure przedstawiający ekran uprawnień interfejsu API dla aplikacji, z wyróżnionymi uprawnieniami programu Microsoft Graph.

Dodaj następujące zależności do pliku pom.xml.

<dependencies>
   <dependency>
       <groupId>com.azure.spring</groupId>
       <artifactId>azure-spring-boot-starter-active-directory-b2c</artifactId>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-thymeleaf</artifactId>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-security</artifactId>
   </dependency>
   <dependency>
       <groupId>org.thymeleaf.extras</groupId>
       <artifactId>thymeleaf-extras-springsecurity6</artifactId>
   </dependency>
</dependencies>

Dodaj właściwości do pliku application.yml przy użyciu utworzonych wcześniej wartości, jak pokazano w poniższym przykładzie:

spring:
 cloud:
   azure:
     active-directory:
       b2c:
         enabled: true
         authenticate-additional-parameters:
           domain_hint: xxxxxxxxx         # optional
           login_hint: xxxxxxxxx          # optional
           prompt: [login,none,consent]   # optional
         base-uri: ${BASE_URI}
         credential:
           client-id: ${WEBAPP_AZURE_CLIENT_ID}
           client-secret: ${WEBAPP_AZURE_CLIENT_SECRET}
         login-flow: ${LOGIN_USER_FLOW_KEY}               # default to sign-up-or-sign-in, will look up the user-flows map with provided key.
         logout-success-url: ${LOGOUT_SUCCESS_URL}
         user-flows:
           ${YOUR_USER_FLOW_KEY}: ${USER_FLOW_NAME}
         user-name-attribute-name: ${USER_NAME_ATTRIBUTE_NAME}

Napisz kod Java.

W przypadku kodu kontrolera możesz zapoznać się z następującym przykładem:

@Controller
public class WebController {

   private void initializeModel(Model model, OAuth2AuthenticationToken token) {
       if (token != null) {
           final OAuth2User user = token.getPrincipal();
           model.addAllAttributes(user.getAttributes());
           model.addAttribute("grant_type", user.getAuthorities());
           model.addAttribute("name", user.getName());
       }
   }

   @GetMapping(value = { "/", "/home" })
   public String index(Model model, OAuth2AuthenticationToken token) {
       initializeModel(model, token);
       return "home";
   }
}

Kod konfiguracji zabezpieczeń można znaleźć w poniższym przykładzie:

@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
public class WebSecurityConfiguration {

    private final AadB2cOidcLoginConfigurer configurer;

    public WebSecurityConfiguration(AadB2cOidcLoginConfigurer configurer) {
        this.configurer = configurer;
    }

    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        // @formatter:off
        http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
            .with(configurer, Customizer.withDefaults());
        // @formatter:on
        return http.build();
    }
}

Skopiuj plik home.html z przykładu i zastąp elementy i nazwami przepływów użytkownika, których użyto wcześniej.

Skompiluj i przetestuj aplikację. Niech Webapp działa na porcie 8080.

Po utworzeniu i uruchomieniu aplikacji przez narzędzie Maven otwórz http://localhost:8080/ w przeglądarce internetowej. Powinno nastąpić przekierowanie do strony logowania.

Wybierz link z przepływem logowania użytkownika. Aby rozpocząć proces uwierzytelniania, nastąpi przekierowanie do usługi Azure AD B2C.

Po pomyślnym zalogowaniu powinieneś zobaczyć z przeglądarki próbkę home page.

Użycie 2. Aplikacja internetowa, która uzyskuje dostęp do serwerów zasobów

Ten scenariusz jest oparty na scenariuszu Uzyskiwanie dostępu do aplikacji internetowej, aby umożliwić aplikacji dostęp do innych zasobów. Ten scenariusz to przepływ poświadczeń klienta OAuth 2.0.

Wybierz usługi Azure AD B2C z menu portalu, wybierz pozycję Aplikacje, a następnie wybierz pozycję Dodaj.

Określ nazwę aplikacji Nazwa (na przykład ), zapisz Identyfikator aplikacji jako , a następnie wybierz opcję Zapisz.

Wybierz pozycję klucze z aplikacji, wybierz pozycję Wygeneruj klucz, aby wygenerować WEB_API_A_AZURE_CLIENT_SECRET, a następnie wybierz pozycję Zapisz.

Wybierz pozycję Udostępnij interfejs API w okienku nawigacji, a następnie wybierz pozycję Ustaw. Zanotuj URI identyfikatora aplikacji jako WEB_API_A_APP_ID_URL, a następnie wybierz Zapisz.

Wybierz Manifest w okienku nawigacyjnym, a następnie wklej następujący fragment kodu JSON do tablicy appRoles. Zapisz URI identyfikatora aplikacji jako WEB_API_A_APP_ID_URL, zapisz wartość roli aplikacji jako WEB_API_A_ROLE_VALUE, a następnie wybierz pozycję Zapisz.

{
 "allowedMemberTypes": [
   "Application"
 ],
 "description": "WebApiA.SampleScope",
 "displayName": "WebApiA.SampleScope",
 "id": "04989db0-3efe-4db6-b716-ae378517d2b7",
 "isEnabled": true,
 "value": "WebApiA.SampleScope"
}

Wybierz pozycję uprawnienia interfejsu API >Dodaj uprawnienie>Moje interfejsy API, wybierz pozycję WebApiA nazwę aplikacji, wybierz uprawnienia aplikacji, wybierz pozycję WebApiA.SampleScope uprawnienia, a następnie wybierz pozycję Dodaj uprawnienia, aby ukończyć proces.

Udziel zgody administratora na uprawnienia WebApiA.

zrzut ekranu witryny Azure Portal przedstawiający ekran uprawnień interfejsu API aplikacji.

Dodaj następującą zależność na podstawie scenariusza Uzyskiwanie dostępu do aplikacji internetowej.

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

Dodaj następującą konfigurację na podstawie scenariusza Uzyskiwanie dostępu do aplikacji internetowej.

spring:
 cloud:
   azure:
     active-directory:
       b2c:
         enabled: true
         base-uri: ${BASE_URI}             # Such as: https://xxxxb2c.b2clogin.com
         profile:
           tenant-id: <tenant>
         authorization-clients:
           ${RESOURCE_SERVER_A_NAME}:
             authorization-grant-type: client_credentials
             scopes: ${WEB_API_A_APP_ID_URL}/.default

Uwaga

Dozwolone wartości dla tenant-id to: common, organizations, consumerslub identyfikator dzierżawy. Aby uzyskać więcej informacji na temat tych wartości, zobacz sekcję Użyto niewłaściwego punktu końcowego (konta osobiste i organizacyjne) w artykule Błąd AADSTS50020 — konto użytkownika od dostawcy tożsamości nie istnieje w dzierżawie. Aby uzyskać informacje na temat konwersji aplikacji z jedną dzierżawą na aplikację wielodzierżawną, zobacz Konwertowanie aplikacji z jedną dzierżawą na aplikację wielodzierżawną w usłudze Microsoft Entra ID.

Napisz swój Webapp kod w języku Java.

W przypadku kodu kontrolera możesz zapoznać się z następującym przykładem:

class Demo {
   /**
    * Access to protected data from Webapp to WebApiA through client credential flow. The access token is obtained by webclient, or
    * <p>@RegisteredOAuth2AuthorizedClient("webApiA")</p>. In the end, these two approaches will be executed to
    * DefaultOAuth2AuthorizedClientManager#authorize method, get the access token.
    *
    * @return Respond to protected data from WebApi A.
    */
   @GetMapping("/webapp/webApiA")
   public String callWebApiA() {
       String body = webClient
           .get()
           .uri(LOCAL_WEB_API_A_SAMPLE_ENDPOINT)
           .attributes(clientRegistrationId("webApiA"))
           .retrieve()
           .bodyToMono(String.class)
           .block();
       LOGGER.info("Call callWebApiA(), request '/webApiA/sample' returned: {}", body);
       return "Request '/webApiA/sample'(WebApi A) returned a " + (body != null ? "success." : "failure.");
   }
}

Kod konfiguracji zabezpieczeń jest taki sam jak w scenariuszu Uzyskiwanie dostępu do aplikacji internetowej. Dodaj kolejny bean webClient, wykonując następujące czynności:

public class SampleConfiguration {
   @Bean
   public WebClient webClient(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
       ServletOAuth2AuthorizedClientExchangeFilterFunction function =
           new ServletOAuth2AuthorizedClientExchangeFilterFunction(oAuth2AuthorizedClientManager);
       return WebClient.builder()
                       .apply(function.oauth2Configuration())
                       .build();
   }
}

Aby napisać kod WebApiA Java, zobacz sekcję Uzyskiwanie dostępu do serwera zasobów.

Skompiluj i przetestuj aplikację. Niech Webapp i WebApiA działają odpowiednio na portach 8080 i 8081. Uruchom aplikacje Webapp i WebApiA. Wróć do strony głównej po pomyślnym zalogowaniu. Następnie możesz uzyskać dostęp do http://localhost:8080/webapp/webApiA, aby uzyskać odpowiedź zasobu WebApiA.

Użycie 3. Uzyskiwanie dostępu do serwera zasobów

Ten scenariusz nie obsługuje logowania. Wystarczy chronić serwer, sprawdzając token dostępu, a jeśli jest prawidłowy, obsługuje żądanie.

Aby skompilować uprawnienia WebApiA, zobacz Użycie 2: Dostęp do serwerów zasobów aplikacji internetowej.

Dodaj uprawnienia WebApiA i udziel zgody administratora dla aplikacji internetowej.

Dodaj następujące zależności do pliku pom.xml.

<dependencies>
   <dependency>
       <groupId>com.azure.spring</groupId>
       <artifactId>azure-spring-boot-starter-active-directory-b2c</artifactId>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
   </dependency>
</dependencies>

Dodaj następującą konfigurację.

spring:
 cloud:
   azure:
     active-directory:
       b2c:
         enabled: true
         base-uri: ${BASE_URI}             # Such as: https://xxxxb2c.b2clogin.com
         profile:
           tenant-id: <tenant>
         app-id-uri: ${APP_ID_URI}         # If you're using v1.0 token, configure app-id-uri for `aud` verification
         credential:
           client-id: ${AZURE_CLIENT_ID}           # If you're using v2.0 token, configure client-id for `aud` verification
         user-flows:
           sign-up-or-sign-in: ${SIGN_UP_OR_SIGN_IN_USER_FLOW_NAME}

Uwaga

Dozwolone wartości dla tenant-id to: common, organizations, consumerslub identyfikator dzierżawy. Aby uzyskać więcej informacji na temat tych wartości, zobacz sekcję Użyto niewłaściwego punktu końcowego (konta osobiste i organizacyjne) w artykule Błąd AADSTS50020 — konto użytkownika od dostawcy tożsamości nie istnieje w dzierżawie. Aby uzyskać informacje na temat konwersji aplikacji z jedną dzierżawą na aplikację wielodzierżawną, zobacz Konwertowanie aplikacji z jedną dzierżawą na aplikację wielodzierżawną w usłudze Microsoft Entra ID.

Napisz kod Java.

W przypadku kodu kontrolera możesz zapoznać się z następującym przykładem:

class Demo {
   /**
    * webApiA resource api for web app
    * @return test content
    */
   @PreAuthorize("hasAuthority('APPROLE_WebApiA.SampleScope')")
   @GetMapping("/webApiA/sample")
   public String webApiASample() {
       LOGGER.info("Call webApiASample()");
       return "Request '/webApiA/sample'(WebApi A) returned successfully.";
   }
}

Kod konfiguracji zabezpieczeń można znaleźć w poniższym przykładzie:

@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableMethodSecurity
public class ResourceServerConfiguration {
    
    @Bean
    public SecurityFilterChain htmlFilterChain(HttpSecurity http) throws Exception {
        JwtAuthenticationConverter authenticationConverter = new JwtAuthenticationConverter();
        JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
        jwtGrantedAuthoritiesConverter.setAuthorityPrefix("APPROLE_");
        authenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
        // @formatter:off
        http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
            .oauth2ResourceServer(o -> o.jwt(j -> j.jwtAuthenticationConverter(authenticationConverter)));
        // @formatter:on
        return http.build();
    }
}

Skompiluj i przetestuj aplikację. Niech WebApiA działa na porcie 8081. Pobierz token dostępu dla zasobu webApiA, a następnie uzyskaj dostęp do http://localhost:8081/webApiA/sample, używając go w nagłówku autoryzacji Bearer.

Użycie 4. Serwer zasobów uzyskuje dostęp do innych serwerów zasobów

Ten scenariusz stanowi rozszerzenie scenariusza Uzyskiwanie dostępu do serwera zasobów i umożliwia dostęp do innych zasobów aplikacji w oparciu o przepływ poświadczeń klienta OAuth2.

Odwołując się do poprzednich kroków, utworzymy aplikację WebApiB i uwidaczniamy uprawnienie aplikacji WebApiB.SampleScope.

{
   "allowedMemberTypes": [
       "Application"
   ],
   "description": "WebApiB.SampleScope",
   "displayName": "WebApiB.SampleScope",
   "id": "04989db0-3efe-4db6-b716-ae378517d2b7",
   "isEnabled": true,
   "lang": null,
   "origin": "Application",
   "value": "WebApiB.SampleScope"
}

Udziel zgody administratora na uprawnienia WebApiB.

zrzut ekranu witryny Azure Portal przedstawiający ekran uprawnień interfejsu API webApiA aplikacji.

Na podstawie Uzyskiwanie dostępu do serwera zasobówdodaj następującą zależność do pliku pom.xml.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

Dodaj następującą konfigurację na podstawie konfiguracji scenariusza Uzyskiwanie dostępu do serwera zasobów.

spring:
 cloud:
   azure:
     active-directory:
       b2c:
         enabled: true
         credential:
           client-secret: ${WEB_API_A_AZURE_CLIENT_SECRET}
         authorization-clients:
           ${RESOURCE_SERVER_B_NAME}:
             authorization-grant-type: client_credentials
             scopes: ${WEB_API_B_APP_ID_URL}/.default

Napisz kod Java.

W przypadku kodu kontrolera WebApiA można zapoznać się z następującym przykładem:

public class SampleController {
   /**
    * Access to protected data from WebApiA to WebApiB through client credential flow. The access token is obtained by webclient, or
    * <p>@RegisteredOAuth2AuthorizedClient("webApiA")</p>. In the end, these two approaches will be executed to
    * DefaultOAuth2AuthorizedClientManager#authorize method, get the access token.
    *
    * @return Respond to protected data from WebApi B.
    */
   @GetMapping("/webApiA/webApiB/sample")
   @PreAuthorize("hasAuthority('APPROLE_WebApiA.SampleScope')")
   public String callWebApiB() {
       String body = webClient
           .get()
           .uri(LOCAL_WEB_API_B_SAMPLE_ENDPOINT)
           .attributes(clientRegistrationId("webApiB"))
           .retrieve()
           .bodyToMono(String.class)
           .block();
       LOGGER.info("Call callWebApiB(), request '/webApiB/sample' returned: {}", body);
       return "Request 'webApiA/webApiB/sample'(WebApi A) returned a " + (body != null ? "success." : "failure.");
   }
}

W przypadku kodu kontrolera WebApiB można zapoznać się z następującym przykładem:

public class SampleController {
   /**
    * webApiB resource api for other web application
    * @return test content
    */
   @PreAuthorize("hasAuthority('APPROLE_WebApiB.SampleScope')")
   @GetMapping("/webApiB/sample")
   public String webApiBSample() {
       LOGGER.info("Call webApiBSample()");
       return "Request '/webApiB/sample'(WebApi B) returned successfully.";
   }
}

Kod konfiguracji zabezpieczeń jest taki sam jak w scenariuszu uzyskiwania dostępu do serwera zasobów, a dodatkowo dodaje się następujący komponent webClient

public class SampleConfiguration {
   @Bean
   public WebClient webClient(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
       ServletOAuth2AuthorizedClientExchangeFilterFunction function =
           new ServletOAuth2AuthorizedClientExchangeFilterFunction(oAuth2AuthorizedClientManager);
       return WebClient.builder()
                       .apply(function.oauth2Configuration())
                       .build();
   }
}

Skompiluj i przetestuj aplikację. Niech WebApiA i WebApiB działają odpowiednio na portach 8081 i 8082. Uruchom aplikacje WebApiA i WebApiB, uzyskaj token dostępu dla zasobu webApiA i uzyskaj dostęp do http://localhost:8081/webApiA/webApiB/sample jako nagłówka autoryzacji elementu nośnego.

Próbki

Aby uzyskać więcej informacji, zobacz spring-cloud-azure-starter-active-directory-b2c przykłady.