본문 바로가기

Web/spring

[Spring] Async Support with Spring MVC and Spring Security

728x90

https://www.baeldung.com/spring-mvc-async-security

 

 

 

비동기 요청에 대한 Servlet 3 과 MVC, Security 에 관련된 내용이다

 

참고로 Spring Security는 MVC 범위 밖에서 @Async 와 통합되고 HTTP 요청도 처리합니다.

implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'

Spring MVC and @Async

WebAsyncManager

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/context/request/async/WebAsyncManager.html

 

WebAsyncManager (Spring Framework 6.0.7 API)

getConcurrentResultContext Provides access to additional processing context saved at the start of concurrent handling. See Also:

docs.spring.io

springSecurityFilterChain 이 비동기 요청을 처리하도록 설정되었는지 확인한다.

dispatcher.setAsyncSupported(true);

 

 

in XML config:

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

 

We also need to enable the async-supported parameter in our servlet configuration:

<servlet>
    ...
    <async-supported>true</async-supported>
    ...
</servlet>

Spring Security 내의 내부 메커니즘은 응답이 다른 스레드 에서 커밋되어

사용자 로그아웃이 발생할 때 SecurityContext가 더 이상 지워지지 않도록 한다

 

 

 

Use Cases

Let's see this in action with a simple example:

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

We want to check if the Spring SecurityContext is propagated to the new thread.

The method presented above will automatically have its Callable executed with the SecurityContext included, as seen in logs:

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_ADMINCopy

Without setting up the SecurityContext to be propagated, the second request will end up with null value.

 

 

 

propagated SecurityContext 와 함께 비동기 요청을 사용하는 다른 중요한 사용 사례도 있다 .

  • 병렬로 실행할 수 있고 실행하는 데 상당한 시간이 걸릴 수 있는 여러 외부 요청을 만들 때.
  • 우리는 로컬에서 수행해야 할 몇 가지 중요한 처리가 있으며 외부 요청을 병렬로 실행할 때.
  • 다른 것들은 예를 들어 이메일 보내기와 같은 실행 후 잊어버리는 시나리오를 나타낼 때.

여러 메서드 호출이 이전에 동기 방식으로 함께 연결된 경우 이를 비동기 방식으로 변환하려면 결과를 동기화해야 할 수 있다.

728x90