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에서 필요한 리소스 만들기
읽기 빠른 시작: Microsoft ID 플랫폼애플리케이션을 등록합니다.
앱 등록을 만듭니다.
AZURE_TENANT_ID
,AZURE_CLIENT_ID
및AZURE_CLIENT_SECRET
가져옵니다.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입니다. 이러한 값에 대한 자세한 내용은
이제 애플리케이션을 시작하고 브라우저를 통해 애플리케이션에 액세스합니다. 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
업데이트합니다.
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에서 필수 리소스 만들기
읽기 빠른 시작: Microsoft ID 플랫폼애플리케이션을 등록합니다.
앱 등록을 만듭니다.
AZURE_TENANT_ID
,AZURE_CLIENT_ID
및AZURE_CLIENT_SECRET
가져옵니다.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입니다. 이러한 값에 대한 자세한 내용은
여기서 graph
OAuth2AuthorizedClient
이름입니다. 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입니다. 이러한 값에 대한 자세한 내용은
여러 리소스 서버에 액세스
한 웹 애플리케이션에서 다음과 같이 구성하여 여러 리소스 서버에 액세스할 수 있습니다.
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입니다. 이러한 값에 대한 자세한 내용은
그런 다음 다음과 같은 애플리케이션에서 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에서 필요한 리소스 만들기
읽기 빠른 시작: Microsoft ID 플랫폼애플리케이션을 등록합니다.
앱 등록을 만듭니다.
AZURE_CLIENT_ID
가져옵니다.읽기 빠른 시작: 웹 API노출하도록 애플리케이션을 구성합니다.
범위가
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에 액세스합니다.
액세스 토큰 없이 401을 받게 됩니다.
액세스 토큰을 사용하여 애플리케이션에 액세스합니다. 액세스 토큰에서 다음 클레임의 유효성이 검사됩니다.
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 플랫폼 액세스 토큰대한
고급 사용량
추가 보안 구성 추가
@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();
}
}
범위별 권한 유효성 검사
Azure에서 필요한 리소스를 만듭니다.
읽기 빠른 시작: 웹 API노출하도록 애플리케이션을 구성합니다.
범위가
Scope1
웹 API를 노출합니다.
특정 메서드를 보호합니다.
class Demo { @GetMapping("scope1") @ResponseBody @PreAuthorize("hasAuthority('SCOPE_Scope1')") public String scope1() { return "Congratulations, you can access `scope1` endpoint."; } }
이렇게 하면 액세스 /scope1
엔드포인트에 액세스할 때 액세스 토큰에서 다음 클레임의 유효성이 검사됩니다.
-
scp
: 값에Scope1
포함되어야 합니다.
앱 역할별 권한 유효성 검사
Azure에서 필요한 리소스를 만듭니다.
애플리케이션에 앱 역할 추가 읽고 토큰받습니다.
다음 매개 변수를 사용하여 앱 역할을 만듭니다.
- 표시 이름: AppRole1
- 허용되는 멤버 유형: 사용자/그룹
- 값: AppRole1
- 이 앱 역할을 사용하도록 설정하시겠습니까? 예
특정 메서드를 보호합니다.
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 웹 토큰)를 사용하려면 다음 단계를 사용합니다.
- microsoft ID 플랫폼 애플리케이션 인증 인증서 자격 증명
Microsoft ID 플랫폼 인증서 등록 섹션을 참조하세요. - Azure Portal에 등록된 애플리케이션에 .pem 인증서를 업로드합니다.
- 인증서 경로 및 암호를 구성합니다. PFX 또는 . P12 인증서입니다.
- 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입니다. 이러한 값에 대한 자세한 내용은
이 예제와 같이 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입니다. 이러한 값에 대한 자세한 내용은
프록시를 통해 Microsoft Entra ID에 연결
프록시를 통해 Microsoft Entra ID를 연결하려면 RestTemplateCustomizer
bean을 제공합니다. 자세한 내용은 프록시 섹션을 통해 Microsoft Entra ID에 연결하는
샘플
샘플 프로젝트: aad-resource-server
다른 리소스 서버를 방문하는 리소스 서버
시스템 다이어그램
다른 리소스 서버를 방문하는 리소스 서버에 대한
Azure에서 필요한 리소스 만들기
읽기 빠른 시작: Microsoft ID 플랫폼애플리케이션을 등록합니다.
앱 등록을 만듭니다.
AZURE_TENANT_ID
,AZURE_CLIENT_ID
및AZURE_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입니다. 이러한 값에 대한 자세한 내용은
애플리케이션에서 OAuth2AuthorizedClient 사용
public class SampleController {
@GetMapping("call-graph")
public String callGraph(@RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient graph) {
return callMicrosoftGraphMeEndpoint(graph);
}
}
샘플
샘플 프로젝트: aad-resource-server-obo
한 애플리케이션의 웹 애플리케이션 및 리소스 서버
Azure에서 필요한 리소스 만들기
읽기 빠른 시작: Microsoft ID 플랫폼애플리케이션을 등록합니다.
앱 등록을 만듭니다.
AZURE_TENANT_ID
,AZURE_CLIENT_ID
및AZURE_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-type
web_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입니다. 이러한 값에 대한 자세한 내용은
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: 웹 애플리케이션 액세스
이 시나리오에서는 OAuth 2.0 권한 부여 코드 부여 흐름을 사용하여 Azure AD B2C 사용자로 사용자를 로그인합니다.
포털 메뉴에서
애플리케이션 이름(예: webapp
)을 지정하고, http://localhost:8080/login/oauth2/code/
대한 추가하고, 응용 프로그램 IDWEB_APP_AZURE_CLIENT_ID
기록한 다음, 저장을 선택합니다.
애플리케이션에서
왼쪽에서 사용자 흐름 선택한 다음 새 사용자 흐름선택합니다.
등록 또는, 프로필 편집및 암호 재설정 선택하여 각각 사용자 흐름을 만듭니다. 사용자 흐름
Graph 권한에 대한 관리자 동의를 부여합니다.
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 샘플
앱을 빌드하고 테스트합니다. 포트 Webapp
실행합니다.
Maven에서 애플리케이션을 빌드하고 시작한 후 웹 브라우저에서 http://localhost:8080/
엽니다. 로그인 페이지로 리디렉션되어야 합니다.
로그인 사용자 흐름이 있는 링크를 선택합니다. 인증 프로세스를 시작하려면 Azure AD B2C를 리디렉션해야 합니다.
성공적으로 로그인하면 브라우저에서 샘플 home page
표시됩니다.
사용량 2: 리소스 서버에 액세스하는 웹 애플리케이션
이 시나리오는 애플리케이션이 다른 리소스에 액세스할 수 있도록 웹 애플리케이션 시나리오에 액세스하는
포털 메뉴에서
애플리케이션
애플리케이션에서
탐색 창에서 API
탐색 창에서 매니페스트 선택한 다음 다음 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"
}
WebApiA 권한에 대한 관리자 동의를 부여합니다.
웹 애플리케이션 시나리오에 액세스하는
<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입니다. 이러한 값에 대한 자세한 내용은
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 코드를 작성하려면 리소스 서버 액세스 섹션을 참조하세요.
앱을 빌드하고 테스트합니다. 포트 Webapp
및 WebApiA
각각 및 실행합니다.
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입니다. 이러한 값에 대한 자세한 내용은
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
리소스 서버액세스하는
<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();
}
}
앱을 빌드하고 테스트합니다. 포트 WebApiA
및 WebApiB
각각 및 실행합니다.
WebApiA
및 WebApiB
애플리케이션을 시작하고, webApiA
리소스에 대한 액세스 토큰을 가져오고, 전달자 권한 부여 헤더로 http://localhost:8081/webApiA/webApiB/sample
액세스합니다.
샘플
자세한 내용은 spring-cloud-azure-starter-active-directory-b2c 샘플