1. 소개
이 빠른 사용방법(예제)에서는 비동기 요청에 대한 Servlet 3 지원과 Spring MVC 및 Spring Security가 이러한 .
웹 애플리케이션에서 비동기성에 대한 가장 기본적인 동기는 장기 실행 요청을 처리하는 것입니다. 대부분의 사용 사례에서 Spring Security 주체가 이러한 스레드로 전파되는지 확인해야 합니다.
물론 Spring Security 는 MVC 범위 밖에서 @Async 와 통합되고 HTTP 요청도 처리합니다.
2. 메이븐 의존성
Spring MVC에서 비동기 통합을 사용하려면 pom.xml 에 다음 의존성을 포함해야 합니다 .
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.7.3</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.7.3</version>
</dependency>
최신 버전의 Spring Security 의존성은 여기 에서 찾을 수 있습니다 .
3. 스프링 MVC와 @Async
공식 문서 에 따르면 Spring Security는 WebAsyncManager 와 통합됩니다 .
첫 번째 단계는 springSecurityFilterChain 이 비동기 요청을 처리하도록 설정되었는지 확인하는 것입니다. Servlet 구성 클래스 에 다음 줄을 추가하여 Java 구성에서 수행할 수 있습니다 .
dispatcher.setAsyncSupported(true);
또는 XML 구성에서:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ASYNC</dispatcher>
</filter-mapping>
또한 서블릿 구성에서 async-supported 매개변수 를 활성화해야 합니다.
<servlet>
...
<async-supported>true</async-supported>
...
</servlet>
이제 우리는 전파된 SecurityContext 와 함께 비동기 요청을 보낼 준비가 되었습니다 .
Spring Security 내의 내부 메커니즘 은 다른 스레드 에서 응답이 커밋되어 사용자 로그아웃 이 발생할 때 SecurityContext 가 더 이상 지워지지 않도록 합니다.
4. 사용 사례
간단한 예를 통해 이를 실제로 살펴보겠습니다.
@Override
public Callable<Boolean> checkIfPrincipalPropagated() {
Object before
= SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.info("Before new thread: " + before);
return new Callable<Boolean>() {
public Boolean call() throws Exception {
Object after
= SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.info("New thread: " + after);
return before == after;
}
};
}
Spring SecurityContext 가 새 스레드로 전파 되는지 확인하고 싶습니다 .
위에 제시된 메소드는 로그에서 볼 수 있듯이 SecurityContext 가 포함된 Callable 을 자동으로 실행합니다 .
web - 2017-01-02 10:42:19,011 [http-nio-8081-exec-3] INFO
o.baeldung.web.service.AsyncService - Before new thread:
org.springframework.security.core.userdetails.User@76507e51:
Username: temporary; Password: [PROTECTED]; Enabled: true;
AccountNonExpired: true; credentialsNonExpired: true;
AccountNonLocked: true; Granted Authorities: ROLE_ADMIN
web - 2017-01-02 10:42:19,020 [MvcAsync1] INFO
o.baeldung.web.service.AsyncService - New thread:
org.springframework.security.core.userdetails.User@76507e51:
Username: temporary; Password: [PROTECTED]; Enabled: true;
AccountNonExpired: true; credentialsNonExpired: true;
AccountNonLocked: true; Granted Authorities: ROLE_ADMIN
전파할 SecurityContext 를 설정하지 않으면 두 번째 요청은 null 값으로 끝납니다.
전파된 SecurityContext 와 함께 비동기 요청을 사용하는 다른 중요한 사용 사례도 있습니다 .
- 병렬로 실행할 수 있고 실행하는 데 상당한 시간이 걸릴 수 있는 여러 외부 요청을 만들고 싶습니다.
- 우리는 로컬에서 수행해야 할 몇 가지 중요한 처리가 있으며 외부 요청을 병렬로 실행할 수 있습니다.
- 다른 것들은 예를 들어 이메일 보내기와 같은 실행 후 잊어버리는 시나리오를 나타냅니다.
여러 메서드 호출이 이전에 동기 방식으로 함께 연결된 경우 이를 비동기 방식으로 변환하려면 결과를 동기화해야 할 수 있습니다.
5. 결론
이 짧은 예제에서는 인증된 컨텍스트에서 비동기 요청을 처리하기 위한 Spring 지원을 설명했습니다 .
프로그래밍 모델의 관점에서 보면 새 기능은 믿을 수 없을 정도로 단순해 보입니다. 그러나 더 깊이 있는 이해가 필요한 측면도 분명히 있습니다.
이 예제는 Github 에서 Maven 프로젝트로도 제공됩니다 .