다음을 통해 공유


Spring Security에 대한 Spring Cloud Azure 지원

이 문서는✅ 버전 4.19.0 ✅ 버전 5.19.0에 적용됩니다.

이 문서에서는 Spring Cloud Azure와 Spring Security를 함께 사용하는 방법을 설명합니다.

Microsoft Entra ID를 사용하는 Spring Security

웹 애플리케이션을 빌드할 때 ID 및 액세스 관리는 항상 기본 요소입니다.

Azure는 클라우드 기반 ID 서비스뿐만 아니라 나머지 Azure 에코시스템과의 긴밀한 통합을 제공하므로 애플리케이션 개발 과정을 민주화할 수 있는 훌륭한 플랫폼을 제공합니다.

Spring Security를 사용하면 강력한 추상화 및 확장 가능한 인터페이스를 사용하여 Spring 기반 애플리케이션을 쉽게 보호할 수 있습니다. 그러나 Spring 프레임워크만큼 강력하지만 특정 ID 공급자에 맞게 조정되지는 않습니다.

spring-cloud-azure-starter-active-directory 웹 애플리케이션을 Microsoft Entra ID(짧은 경우 Microsoft Entra ID) 테넌트에 연결하고 Microsoft Entra ID로 리소스 서버를 보호하는 가장 최적의 방법을 제공합니다. Oauth 2.0 프로토콜을 사용하여 웹 애플리케이션 및 리소스 서버를 보호합니다.

웹 애플리케이션 액세스

이 시나리오에서는 OAuth 2.0 권한 부여 코드 부여 흐름을 사용하여 Microsoft 계정으로 사용자를 로그인합니다.

시스템 다이어그램

독립 실행형 웹 애플리케이션에 대한 시스템 다이어그램입니다.

Azure에서 필요한 리소스 만들기

  1. 읽기 빠른 시작: Microsoft ID 플랫폼애플리케이션을 등록합니다.

  2. 앱 등록을 만듭니다. AZURE_TENANT_ID, AZURE_CLIENT_IDAZURE_CLIENT_SECRET가져옵니다.

  3. redirect URI APPLICATION_BASE_URI/login/oauth2/code/ 설정합니다(예: http://localhost:8080/login/oauth2/code/). 테일링 / 필요합니다.

필수 종속성 추가

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

필수 속성 추가

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

메모

tenant-id 허용되는 값은 common, organizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 잘못된 엔드포인트(개인 및 조직 계정) 섹션을 참조하세요. - ID 공급자의 사용자 계정이 테넌트존재하지 않습니다. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

이제 애플리케이션을 시작하고 브라우저를 통해 애플리케이션에 액세스합니다. Microsoft 로그인 페이지로 리디렉션됩니다.

고급 사용량

추가 보안 구성 추가
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableMethodSecurity
public class AadOAuth2LoginSecurityConfig {

   /**
    * Add configuration logic as needed.
    */
   @Bean
   SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
       http.apply(AadWebApplicationHttpSecurityConfigurer.aadWebApplication())
               .and()
           .authorizeHttpRequests()
               .anyRequest().authenticated();
           // Do some custom configuration.
       return http.build();
   }
}
앱 역할별 액세스 권한 부여

Azure에서 필요한 리소스를 만듭니다.

  • 애플리케이션에 앱 역할 추가 읽고 토큰받습니다.

  • 다음 매개 변수를 사용하여 앱 역할을 만듭니다.

    • 표시 이름: 관리자
    • 허용되는 멤버 유형: 사용자/그룹
    • 값: 관리자
    • 이 앱 역할을 사용하도록 설정하시겠습니까? 예

메모

앱 역할 기반 액세스 제어를 사용하려는 경우 그룹 이름을 role 클레임에 넣을 수 없습니다. 자세한 내용은 앱선택적 클레임 제공 그룹 선택적 클레임 구성 섹션을 참조하세요.

특정 메서드를 보호합니다.

class Demo {
   @GetMapping("Admin")
   @ResponseBody
   @PreAuthorize("hasAuthority('APPROLE_Admin')")
   public String admin() {
       return "Admin message";
   }
}
그룹 이름 또는 그룹 ID별 액세스 권한 부여

관련 구성 속성을 추가합니다.

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

특정 메서드를 보호합니다.

@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";
   }
}
글로벌 Azure 대신 National Azure 사용

이제 글로벌 Azure 클라우드를 제외하고 Microsoft Entra ID는 다음 국가별 클라우드에 배포됩니다.

  • Azure Government

  • Azure 중국 21Vianet

  • Azure 독일

다음은 Azure 중국 21Vianet을 사용하는 샘플입니다.

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

자세한 내용은 국가별 클라우드 배포참조하세요.

리디렉션 URI 템플릿 구성

개발자는 redirect-uri를 사용자 지정할 수 있습니다.

리디렉션 URI에 대한 시스템 다이어그램을 .

redirect-uri-template 파일에 속성을 추가합니다.

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

Azure Portal에서 redirect-uri 업데이트합니다.

리디렉션 URI 템플릿을 구성합니다.

redirect-uri-template설정한 후 보안 작성기를 업데이트해야 합니다.

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

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

프록시를 통해 Microsoft Entra ID에 연결

프록시를 통해 Microsoft Entra ID를 연결하려면 다음 예제와 같이 RestTemplateCustomizer bean을 제공합니다.

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

샘플

샘플 프로젝트: aad-web-application.

리소스 서버에 액세스하는 웹 애플리케이션

시스템 다이어그램

리소스 서버에 액세스하는 웹 애플리케이션에 대한 시스템 다이어그램입니다.

Azure에서 필수 리소스 만들기

  1. 읽기 빠른 시작: Microsoft ID 플랫폼애플리케이션을 등록합니다.

  2. 앱 등록을 만듭니다. AZURE_TENANT_ID, AZURE_CLIENT_IDAZURE_CLIENT_SECRET가져옵니다.

  3. redirect URI APPLICATION_BASE_URI/login/oauth2/code/설정합니다(예: http://localhost:8080/login/oauth2/code/). 테일링 / 필요합니다.

필수 종속성 추가

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

필수 속성 추가

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

메모

tenant-id 허용되는 값은 common, organizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 잘못된 엔드포인트(개인 및 조직 계정) 섹션을 참조하세요. - ID 공급자의 사용자 계정이 테넌트존재하지 않습니다. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

여기서 graphOAuth2AuthorizedClient이름입니다. scopes 로그인할 때 동의해야 하는 범위를 의미합니다.

애플리케이션에서 OAuth2AuthorizedClient 사용

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

이제 애플리케이션을 시작하고 브라우저에서 애플리케이션에 액세스합니다. 그런 다음 Microsoft 로그인 페이지로 리디렉션됩니다.

고급 사용량

클라이언트 자격 증명 흐름

기본 흐름은 권한 부여 코드 흐름, 클라이언트 자격 증명 흐름사용하려는 경우 다음과 같이 구성할 수 있습니다.

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

메모

tenant-id 허용되는 값은 common, organizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 잘못된 엔드포인트(개인 및 조직 계정) 섹션을 참조하세요. - ID 공급자의 사용자 계정이 테넌트존재하지 않습니다. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

여러 리소스 서버에 액세스

한 웹 애플리케이션에서 다음과 같이 구성하여 여러 리소스 서버에 액세스할 수 있습니다.

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

메모

tenant-id 허용되는 값은 common, organizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 잘못된 엔드포인트(개인 및 조직 계정) 섹션을 참조하세요. - ID 공급자의 사용자 계정이 테넌트존재하지 않습니다. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

그런 다음 다음과 같은 애플리케이션에서 OAuth2AuthorizedClient 사용할 수 있습니다.

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

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

샘플

샘플 프로젝트: aad-web-application.

리소스 서버 액세스

이 시나리오는 로그인을 지원하지 않고 액세스 토큰의 유효성을 검사하여 서버를 보호합니다. 액세스 토큰이 유효한 경우 서버는 요청을 제공합니다.

시스템 다이어그램

독립 실행형 리소스 서버 사용에 대한 시스템 다이어그램

Azure에서 필요한 리소스 만들기

  1. 읽기 빠른 시작: Microsoft ID 플랫폼애플리케이션을 등록합니다.

  2. 앱 등록을 만듭니다. AZURE_CLIENT_ID가져옵니다.

  3. 읽기 빠른 시작: 웹 API노출하도록 애플리케이션을 구성합니다.

  4. 범위가 Scope-1웹 API를 노출합니다.

필수 종속성 추가

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

필수 속성 추가

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

이제 애플리케이션을 시작하고 애플리케이션의 웹 API에 액세스합니다.

  1. 액세스 토큰 없이 401을 받게 됩니다.

  2. 액세스 토큰을 사용하여 애플리케이션에 액세스합니다. 액세스 토큰에서 다음 클레임의 유효성이 검사됩니다.

    • iss: Microsoft Entra ID에서 액세스 토큰을 발급해야 합니다.

    • nbf: 현재 시간은 nbf이전일 수 없습니다.

    • exp: 현재 시간은 exp이후일 수 없습니다.

    • aud: spring.cloud.azure.active-directory.credential.client-id 또는 spring.cloud.azure.active-directory.credential.app-id-uri 구성된 경우 대상 그룹은 구성된 client-id 또는 app-id-uri같아야 합니다. 두 속성이 구성되지 않으면 이 클레임의 유효성이 검사되지 않습니다.

액세스 토큰에 대한 자세한 내용은 microsoft ID 플랫폼 액세스 토큰대한 MS 문서를 참조하세요.

고급 사용량

추가 보안 구성 추가
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableMethodSecurity
public class AadOAuth2ResourceServerSecurityConfig {

    /**
     * Add configuration logic as needed.
     */
    @Bean
    public SecurityFilterChain htmlFilterChain(HttpSecurity http) throws Exception {
        // @formatter:off
        http.apply(AadResourceServerHttpSecurityConfigurer.aadResourceServer())
            .and()
            .authorizeHttpRequests()
            .anyRequest().authenticated();
        // @formatter:on
        return http.build();
    }
}
범위별 권한 유효성 검사
  1. Azure에서 필요한 리소스를 만듭니다.

  2. 특정 메서드를 보호합니다.

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

이렇게 하면 액세스 /scope1 엔드포인트에 액세스할 때 액세스 토큰에서 다음 클레임의 유효성이 검사됩니다.

  • scp: 값에 Scope1포함되어야 합니다.
앱 역할별 권한 유효성 검사
  1. Azure에서 필요한 리소스를 만듭니다.

    • 애플리케이션에 앱 역할 추가 읽고 토큰받습니다.

    • 다음 매개 변수를 사용하여 앱 역할을 만듭니다.

      • 표시 이름: AppRole1
      • 허용되는 멤버 유형: 사용자/그룹
      • 값: AppRole1
      • 이 앱 역할을 사용하도록 설정하시겠습니까? 예
  2. 특정 메서드를 보호합니다.

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

이렇게 하면 액세스 /app-role1 엔드포인트에 액세스할 때 액세스 토큰에서 다음 클레임의 유효성이 검사됩니다.

  • roles: 값에 AppRole1포함되어야 합니다.
JWT 클라이언트 인증 사용

클라이언트 인증에 JWT(JSON 웹 토큰)를 사용하려면 다음 단계를 사용합니다.

  1. microsoft ID 플랫폼 애플리케이션 인증 인증서 자격 증명Microsoft ID 플랫폼 인증서 등록 섹션을 참조하세요.
  2. Azure Portal에 등록된 애플리케이션에 .pem 인증서를 업로드합니다.
  3. 인증서 경로 및 암호를 구성합니다. PFX 또는 . P12 인증서입니다.
  4. JWT 클라이언트 인증을 통해 인증할 클라이언트에 속성 spring.cloud.azure.active-directory.authorization-clients.azure.client-authentication-method=private_key_jwt 구성을 추가합니다.

다음 예제 구성 파일은 웹 애플리케이션 시나리오용입니다. 인증서 정보는 전역 속성에 구성됩니다.

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

메모

tenant-id 허용되는 값은 common, organizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 잘못된 엔드포인트(개인 및 조직 계정) 섹션을 참조하세요. - ID 공급자의 사용자 계정이 테넌트존재하지 않습니다. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

이 예제와 같이 active-directory 서비스 속성에서 인증서 정보를 구성할 수도 있습니다.

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

메모

tenant-id 허용되는 값은 common, organizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 잘못된 엔드포인트(개인 및 조직 계정) 섹션을 참조하세요. - ID 공급자의 사용자 계정이 테넌트존재하지 않습니다. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

프록시를 통해 Microsoft Entra ID에 연결

프록시를 통해 Microsoft Entra ID를 연결하려면 RestTemplateCustomizer bean을 제공합니다. 자세한 내용은 프록시 섹션을 통해 Microsoft Entra ID에 연결하는 참조하세요.

샘플

샘플 프로젝트: aad-resource-server.

다른 리소스 서버를 방문하는 리소스 서버

시스템 다이어그램

다른 리소스 서버를 방문하는 리소스 서버에 대한 시스템 다이어그램

Azure에서 필요한 리소스 만들기

  1. 읽기 빠른 시작: Microsoft ID 플랫폼애플리케이션을 등록합니다.

  2. 앱 등록을 만듭니다. AZURE_TENANT_ID, AZURE_CLIENT_IDAZURE_CLIENT_SECRET가져옵니다.

필수 종속성 추가

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

필수 속성 추가

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

메모

tenant-id 허용되는 값은 common, organizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 잘못된 엔드포인트(개인 및 조직 계정) 섹션을 참조하세요. - ID 공급자의 사용자 계정이 테넌트존재하지 않습니다. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

애플리케이션에서 OAuth2AuthorizedClient 사용

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

샘플

샘플 프로젝트: aad-resource-server-obo.

한 애플리케이션의 웹 애플리케이션 및 리소스 서버

Azure에서 필요한 리소스 만들기

  1. 읽기 빠른 시작: Microsoft ID 플랫폼애플리케이션을 등록합니다.

  2. 앱 등록을 만듭니다. AZURE_TENANT_ID, AZURE_CLIENT_IDAZURE_CLIENT_SECRET가져옵니다.

필수 종속성 추가

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

필수 속성 추가

속성 spring.cloud.azure.active-directory.application-typeweb_application_and_resource_server설정하고 각 권한 부여 클라이언트에 대한 권한 부여 유형을 지정합니다.

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

메모

tenant-id 허용되는 값은 common, organizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 잘못된 엔드포인트(개인 및 조직 계정) 섹션을 참조하세요. - ID 공급자의 사용자 계정이 테넌트존재하지 않습니다. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

SecurityFilterChain 정의

여러 SecurityFilterChain 인스턴스를 구성합니다. AadWebApplicationAndResourceServerConfig 리소스 서버 및 웹 애플리케이션에 대한 두 가지 보안 필터 체인 구성을 포함합니다.

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

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

    @Bean
    public SecurityFilterChain htmlFilterChain(HttpSecurity http) throws Exception {
        // @formatter:off
        http.apply(AadWebApplicationHttpSecurityConfigurer.aadWebApplication())
                .and()
            .authorizeHttpRequests()
                .requestMatchers("/login").permitAll()
                .anyRequest().authenticated();
        // @formatter:on
        return http.build();
    }
}

구성

spring-cloud-azure-starter-active-directory의 구성 가능한 속성:

이름 묘사
spring.cloud.azure.active-directory.app-id-uri id_token "aud" 클레임에 사용될 수 있는 앱 ID URI입니다.
spring.cloud.azure.active-directory.application-type Microsoft Entra 애플리케이션의 유형입니다.
spring.cloud.azure.active-directory.authenticate-additional-parameters를 권한 부여 URL에 매개 변수를 추가합니다.
spring.cloud.azure.active-directory.authorization-clients를 OAuth2 권한 부여 클라이언트입니다.
spring.cloud.azure.active-directory.credential.client-id를 Azure에서 서비스 주체 인증을 수행할 때 사용할 클라이언트 ID입니다.
spring.cloud.azure.active-directory.credential.client-secret을 Azure에서 서비스 주체 인증을 수행할 때 사용할 클라이언트 암호입니다.
spring.cloud.azure.active-directory.jwk-set-cache-lifespan을 만료되기 전에 캐시된 JWK 집합의 수명은 기본값인 5분입니다.
spring.cloud.azure.active-directory.jwk-set-cache-refresh-time 캐시된 JWK가 만료되기 전에 설정한 새로 고침 시간(기본값은 5분)입니다.
spring.cloud.azure.active-directory.jwt-connect-timeout JWKSet 원격 URL 호출에 대한 연결 시간 제한입니다.
spring.cloud.azure.active-directory.jwt-read-timeout을 JWKSet 원격 URL 호출에 대한 시간 제한을 읽습니다.
spring.cloud.azure.active-directory.jwt-size-limit JWKSet 원격 URL 호출의 크기 제한(바이트)입니다.
spring.cloud.azure.active-directory.post-logout-redirect-uri를 로그아웃 후 리디렉션 URI입니다.
spring.cloud.azure.active-directory.profile.cloud-type 연결할 Azure 클라우드의 이름입니다. 지원되는 형식은 AZURE, AZURE_CHINA, AZURE_GERMANY, AZURE_US_GOVERNMENT, OTHER입니다.
spring.cloud.azure.active-directory.profile.environment Microsoft Entra 엔드포인트에 대한 속성입니다.
spring.cloud.azure.active-directory.profile.tenant-id를 Azure 테넌트 ID입니다. tenant-id 허용되는 값은 common, organizations, consumers또는 테넌트 ID입니다.
spring.cloud.azure.active-directory.redirect-uri-template을 리디렉션 엔드포인트: 권한 부여 서버에서 리소스 소유자 사용자 에이전트를 통해 권한 부여 자격 증명이 포함된 응답을 클라이언트에 반환하는 데 사용됩니다. 기본값은 {baseUrl}/login/oauth2/code/.
spring.cloud.azure.active-directory.resource-server.claim-to-authority-prefix-map GrantedAuthority를 빌드하는 데 사용할 클레임과 GrantedAuthority 문자열 값의 접두사를 구성합니다. 기본값은 "scp" -> "SCOPE_", "roles" -> "APPROLE_"입니다.
spring.cloud.azure.active-directory.resource-server.principal-claim-name을 AuthenticatedPrincipal#getName에서 반환될 액세스 토큰의 클레임을 구성합니다. 기본값은 "sub"입니다.
spring.cloud.azure.active-directory.session-stateless를 true이면 상태 비정상 인증 필터 AadAppRoleStatelessAuthenticationFilter를 활성화합니다. 기본값은 AadAuthenticationFilter를 활성화하는 false입니다.
spring.cloud.azure.active-directory.user-group.allowed-group-ids를 그룹 ID를 사용하여 GrantedAuthority를 생성할 수 있습니다.
spring.cloud.azure.active-directory.user-group.allowed-group-names를 그룹 이름을 사용하여 GrantedAuthority를 생성할 수 있습니다.
spring.cloud.azure.active-directory.user-group.use-transitive-members를 "true"이면 "v1.0/me/transitiveMemberOf"를 사용하여 멤버를 가져옵니다. 그렇지 않으면 "v1.0/me/memberOf"를 사용합니다. 기본값은 false.
spring.cloud.azure.active-directory.user-name-attribute 보안 주체의 이름이 될 클레임을 결정합니다.

이러한 속성을 사용하는 방법에 대한 몇 가지 예는 다음과 같습니다.

애플리케이션 유형

spring-security-oauth2-client 또는 spring-security-oauth2-resource-server종속성에서 애플리케이션 유형을 유추할 수 있습니다. 유추된 값이 원하는 값이 아닌 경우 애플리케이션 유형을 지정할 수 있습니다. 유효한 값과 유추된 값의 테이블은 다음과 같습니다.

spring-cloud-azure-starter-active-directory애플리케이션 유형:

종속성: spring-security-oauth2-client 종속성: spring-security-oauth2-resource-server 애플리케이션 유형의 유효한 값 유추된 값
아니요 web_application web_application
아니요 resource_server resource_server
web_application, resource_server, resource_server_with_obo, web_application_and_resource_server resource_server_with_obo

Azure Active Directory B2C를 사용하는 Spring Security

Azure AD(Azure Active Directory) B2C는 고객이 애플리케이션을 사용할 때 자신의 프로필을 등록, 로그인 및 관리하는 방법을 사용자 지정하고 제어할 수 있는 ID 관리 서비스입니다. Azure AD B2C를 사용하면 고객의 ID를 동시에 보호하면서 이러한 작업을 수행할 수 있습니다.

종속성 설정

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

구성

spring-cloud-azure-starter-active-directory-b2c의 구성 가능한 속성:

이름 묘사
spring.cloud.azure.active-directory.b2c.app-id-uri를 토큰의 "aud" 클레임에 사용될 수 있는 앱 ID URI입니다.
spring.cloud.azure.active-directory.b2c.authenticate-additional-parameters를 인증에 대한 추가 매개 변수입니다.
spring.cloud.azure.active-directory.b2c.authorization-clients를 클라이언트 구성을 지정합니다.
spring.cloud.azure.active-directory.b2c.base-uri를 Azure AD B2C 엔드포인트 기본 URI.
spring.cloud.azure.active-directory.b2c.credential Azure AD B2C 자격 증명 정보입니다.
spring.cloud.azure.active-directory.b2c.jwt-connect-timeout을 JWKSet 원격 URL 호출에 대한 연결 시간 제한입니다.
spring.cloud.azure.active-directory.b2c.jwt-read-timeout을 JWKSet 원격 URL 호출에 대한 시간 제한을 읽습니다.
spring.cloud.azure.active-directory.b2c.jwt-size-limit JWKSet 원격 URL 호출의 크기 제한(바이트)입니다.
spring.cloud.azure.active-directory.b2c.login-flow를 기본 로그인 흐름 키를 지정합니다. 기본값은 sign-up-or-sign-in.
spring.cloud.azure.active-directory.b2c.logout-success-url을 로그아웃 후 URL을 리디렉션합니다. 기본값은 http://localhost:8080/login.
spring.cloud.azure.active-directory.b2c.profile을 Azure AD B2C 프로필 정보입니다.
spring.cloud.azure.active-directory.b2c.reply-url을 권한 부여 코드를 받은 후 회신 URL입니다. 기본값은 {baseUrl}/login/oauth2/code/.
spring.cloud.azure.active-directory.b2c.user-flows를 사용자 흐름.
spring.cloud.azure.active-directory.b2c.user-name-attribute-name을 사용자 이름 특성 이름입니다.

전체 구성은 spring Cloud Azure 구성 속성확인하세요.

기본 사용량

웹 애플리케이션 사용자가 Microsoft Entra ID로 로그인할 수 있는 웹 기반 애플리케이션인 반면, 리소스 서버 Microsoft Entra ID에서 가져온 access_token 유효성을 검사한 후 액세스를 허용하거나 거부합니다. 이 가이드에서는 4가지 시나리오를 다룹니다.

  1. 웹 애플리케이션에 액세스합니다.

  2. 리소스 서버에 액세스하는 웹 애플리케이션입니다.

  3. 리소스 서버에 액세스합니다.

  4. 다른 리소스 서버에 액세스하는 리소스 서버입니다.

사용량 1: 웹 애플리케이션 액세스

이 시나리오에서는 OAuth 2.0 권한 부여 코드 부여 흐름을 사용하여 Azure AD B2C 사용자로 사용자를 로그인합니다.

포털 메뉴에서 Azure AD B2C 선택하고, 애플리케이션선택한 다음,추가 선택합니다.

애플리케이션 이름(예: webapp)을 지정하고, http://localhost:8080/login/oauth2/code/대한 추가하고, 응용 프로그램 IDWEB_APP_AZURE_CLIENT_ID기록한 다음, 저장을 선택합니다.

애플리케이션에서 선택하고, 키 생성 선택하여 생성한 다음,저장 선택합니다.

왼쪽에서 사용자 흐름 선택한 다음 새 사용자 흐름선택합니다.

등록 또는, 프로필 편집암호 재설정 선택하여 각각 사용자 흐름을 만듭니다. 사용자 흐름 이름 지정하고 사용자 특성 및 클레임만들기선택합니다.

API 사용 권한Microsoft API사용 권한 추가, Microsoft Graph선택, 위임된 권한선택, offline_access 선택하고 openid 권한을 권한 추가 선택하여 프로세스를 완료합니다.

Graph 권한에 대한 관리자 동의를 부여합니다.

그래프 권한이 강조 표시된 앱에 대한 API 권한 화면을 보여 주는 Azure Portal 스크린샷

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>

다음 예제와 같이 이전에 만든 값을 사용하여 application.yml 파일에 속성을 추가합니다.

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}

Java 코드를 작성합니다.

컨트롤러 코드의 경우 다음 예제를 참조할 수 있습니다.

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

보안 구성 코드의 경우 다음 예제를 참조할 수 있습니다.

@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()
                .anyRequest().authenticated()
                .and()
            .apply(configurer);
        // @formatter:on
        return http.build();
    }
}

aad-b2c-web-application 샘플home.html 복사하고 이전에 사용한 사용자 흐름 이름으로 바꿉니다.

앱을 빌드하고 테스트합니다. 포트 Webapp 실행합니다.

Maven에서 애플리케이션을 빌드하고 시작한 후 웹 브라우저에서 http://localhost:8080/ 엽니다. 로그인 페이지로 리디렉션되어야 합니다.

로그인 사용자 흐름이 있는 링크를 선택합니다. 인증 프로세스를 시작하려면 Azure AD B2C를 리디렉션해야 합니다.

성공적으로 로그인하면 브라우저에서 샘플 home page 표시됩니다.

사용량 2: 리소스 서버에 액세스하는 웹 애플리케이션

이 시나리오는 애플리케이션이 다른 리소스에 액세스할 수 있도록 웹 애플리케이션 시나리오에 액세스하는 기반으로 합니다. 이 시나리오는 OAuth 2.0 클라이언트 자격 증명 부여 흐름을 .

포털 메뉴에서 Azure AD B2C 선택하고, 애플리케이션선택한 다음,추가 선택합니다.

애플리케이션 이름(예: )을 지정하고 애플리케이션 ID 기록한 다음저장 선택합니다.

애플리케이션에서 선택하고, 키 생성 선택하여 생성한 다음,저장 선택합니다.

탐색 창에서 API 공개한 다음설정을 선택합니다. 애플리케이션 ID URI 기록한 다음저장 선택합니다.

탐색 창에서 매니페스트 선택한 다음 다음 JSON 세그먼트를 appRoles 배열에 붙여넣습니다. 애플리케이션 ID URIWEB_API_A_APP_ID_URL기록하고 앱 역할의 값을 WEB_API_A_ROLE_VALUE기록한 다음 저장을 선택합니다.

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

API 사용 권한내 API사용 권한 추가, WebApiA 애플리케이션 이름 , 애플리케이션 사용 권한선택, WebApiA.SampleScope 권한 선택한 다음, 권한 추가 선택하여 프로세스를 완료합니다.

WebApiA 권한에 대한 관리자 동의를 부여합니다.

Azure Portal 스크린샷은 애플리케이션 API 권한 화면을 보여 줍니다.

웹 애플리케이션 시나리오에 액세스하는 기반으로 다음 종속성을 추가합니다.

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

웹 애플리케이션 시나리오에 액세스하는 기반으로 다음 구성을 추가합니다.

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

메모

tenant-id 허용되는 값은 common, organizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 잘못된 엔드포인트(개인 및 조직 계정) 섹션을 참조하세요. - ID 공급자의 사용자 계정이 테넌트존재하지 않습니다. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

Webapp Java 코드를 작성합니다.

컨트롤러 코드의 경우 다음 예제를 참조할 수 있습니다.

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

보안 구성 코드는 웹 애플리케이션 시나리오에 액세스하는 것과 동일합니다. 다음과 같이 다른 콩 webClient 추가합니다.

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

WebApiA Java 코드를 작성하려면 리소스 서버 액세스 섹션을 참조하세요.

앱을 빌드하고 테스트합니다. 포트 WebappWebApiA 각각 실행합니다. Webapp 시작하고 애플리케이션을 WebApiA. 성공적으로 로그인한 후 홈 페이지로 돌아갑니다. 그런 다음 http://localhost:8080/webapp/webApiA 액세스하여 WebApiA 리소스 응답을 가져올 수 있습니다.

사용량 3: 리소스 서버 액세스

이 시나리오는 로그인을 지원하지 않습니다. 액세스 토큰의 유효성을 검사하여 서버를 보호하고 유효한 경우 요청을 제공합니다.

WebApiA 권한을 빌드하려면 사용량 2: 리소스 서버에 액세스하는 웹 애플리케이션참조하세요.

WebApiA 권한을 추가하고 웹 애플리케이션에 대한 관리자 동의를 부여합니다.

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>

다음 구성을 추가합니다.

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}

메모

tenant-id 허용되는 값은 common, organizations, consumers또는 테넌트 ID입니다. 이러한 값에 대한 자세한 내용은 오류 AADSTS50020 잘못된 엔드포인트(개인 및 조직 계정) 섹션을 참조하세요. - ID 공급자의 사용자 계정이 테넌트존재하지 않습니다. 단일 테넌트 앱을 변환하는 방법에 대한 자세한 내용은 Microsoft Entra ID단일 테넌트 앱을 다중 테넌트로 변환을 참조하세요.

Java 코드를 작성합니다.

컨트롤러 코드의 경우 다음 예제를 참조할 수 있습니다.

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

보안 구성 코드의 경우 다음 예제를 참조할 수 있습니다.

@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((requests) -> requests.anyRequest().authenticated())
            .oauth2ResourceServer()
            .jwt()
            .jwtAuthenticationConverter(authenticationConverter);
        // @formatter:on
        return http.build();
    }
}

앱을 빌드하고 테스트합니다. 포트 WebApiA 실행합니다. webApiA 리소스에 대한 액세스 토큰을 가져오고 전달자 권한 부여 헤더로 http://localhost:8081/webApiA/sample 액세스합니다.

사용량 4: 다른 리소스 서버에 액세스하는 리소스 서버

이 시나리오는 리소스 서버액세스하는 업그레이드이며 OAuth2 클라이언트 자격 증명 흐름에 따라 다른 애플리케이션 리소스에 대한 액세스를 지원합니다.

이전 단계를 참조하여 WebApiB 애플리케이션을 만들고 애플리케이션 권한 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"
}

WebApiB 권한에 대한 관리자 동의를 부여합니다.

애플리케이션 WebApiA API 권한 화면을 보여 주는 Azure Portal 스크린샷

리소스 서버액세스하는 기반으로 pom.xml 파일에 다음 종속성을 추가합니다.

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

리소스 서버 시나리오 구성에 액세스하는 기반으로 다음 구성을 추가합니다.

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

Java 코드를 작성합니다.

WebApiA 컨트롤러 코드의 경우 다음 예제를 참조할 수 있습니다.

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

WebApiB 컨트롤러 코드의 경우 다음 예제를 참조할 수 있습니다.

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

보안 구성 코드는 리소스 서버 시나리오에 액세스하는 동일하며, 다른 콩 다음과 같이 추가됩니다.

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

앱을 빌드하고 테스트합니다. 포트 WebApiAWebApiB 각각 실행합니다. WebApiAWebApiB 애플리케이션을 시작하고, webApiA 리소스에 대한 액세스 토큰을 가져오고, 전달자 권한 부여 헤더로 http://localhost:8081/webApiA/webApiB/sample 액세스합니다.

샘플

자세한 내용은 spring-cloud-azure-starter-active-directory-b2c 샘플참조하세요.