Spring MVC 和 Spring Security 中的 Servlet 3 異步支持

Spring MVC,Spring Security
Remote
1
10:01 PM · Nov 29 ,2025

1. 簡介在本快速教程中,我們將重點介紹 Servlet 3 對異步請求的支持,以及 Spring MVC 和 Spring Security 如何處理這些請求

異步請求的最基本動機是在 Web 應用程序中處理長時間運行的請求。在大多數用例中,我們需要確保 Spring Security 主體能夠傳遞到這些線程。

當然,Spring Security 與 @Async 集成,不在 MVC 的範圍內,也不作為 HTTP 請求進行處理。

2. Maven 依賴項

為了使用 Spring MVC 中的異步集成,我們需要將以下依賴項包含到我們的 pom.xml 中:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>6.1.5</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>6.1.5</version>
</dependency>

Spring Security 依賴項的最新版本可以在 這裏

3. Spring MVC 和 @Async

根據官方 文檔,Spring Security 與 WebAsyncManager 集成。

第一步是確保我們的 springSecurityFilterChain 已配置為處理異步請求。我們可以通過在 Java 配置中添加以下行來完成,添加到我們的 Servlet 配置類中:

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>

我們還需要在 servlet 配置中啓用 async-supported 參數:


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

現在我們準備好使用 SecurityContext 傳播的異步請求。

Spring Security 內部機制將確保當響應在另一個 Thread 中提交時,我們的 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 是否傳播到新線程。

上面呈現的方法將自動執行其 Callable,包括 SecurityContext,如日誌中所示:

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 支持。

從編程模型角度來看,這些新功能乍一看似乎很簡單。但確實有一些方面需要更深入的理解。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.