X.509 認證
X.509 證書認證最常見的用途是在使用 SSL 時驗證伺服器身份,最常見的是從瀏覽器使用 HTTPS 時。瀏覽器會自動檢查伺服器提供的證書是否由其維護的受信任證書頒發機構列表中的一個頒發(數字簽名)。
您也可以使用“相互認證”的 SSL。伺服器隨後在 SSL 握手期間向客戶端請求一個有效證書。伺服器透過檢查客戶端證書是否由可接受的機構簽名來認證客戶端。如果提供了有效證書,則可以透過應用程式中的 servlet API 獲取。例如,如果您使用 Tomcat,您應該閱讀 Tomcat SSL 說明。在嘗試與 Spring Security 配合使用之前,您應該先使其正常工作。
Spring Security X.509 模組透過使用過濾器提取證書。它將證書對映到應用程式使用者,並載入該使用者的授權集,以便與標準 Spring Security 基礎設施一起使用,特別是當使用 HttpSecurity DSL 時,至少包括 FACTOR_X509 授權。
向您的 Web 應用程式新增 X.509 認證
與響應式 X.509 認證類似,servlet x509 認證過濾器允許從客戶端提供的證書中提取認證令牌。
以下示例展示了響應式 x509 安全配置
-
Java
-
Kotlin
-
Xml
@Bean
DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
http
.x509(Customizer.withDefaults())
.authorizeHttpRequests((exchanges) -> exchanges
.anyRequest().authenticated()
);
return http.build();
}
@Bean
fun springSecurity(http: HttpSecurity): DefaultSecurityFilterChain? {
http {
authorizeHttpRequests {
authorize(anyRequest, authenticated)
}
x509 { }
}
return http.build()
}
<http>
<intercept-url pattern="/**" access="authenticated"/>
<x509 />
</http>
在上述配置中,當未提供 principalExtractor 和 authenticationManager 時,將使用預設值。預設的主體提取器是 SubjectX500PrincipalExtractor,它從客戶端提供的證書中提取 CN(通用名稱)欄位。預設的認證管理器是 ReactivePreAuthenticatedAuthenticationManager,它執行使用者賬戶驗證,檢查是否存在由 principalExtractor 提取的名稱的使用者賬戶,並且該賬戶未被鎖定、停用或過期。
以下示例演示瞭如何覆蓋這些預設值
-
Java
-
Kotlin
-
Xml
@Bean
DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
SubjectX500PrincipalExtractor principalExtractor = new SubjectX500PrincipalExtractor();
principalExtractor.setExtractPrincipalNameFromEmail(true);
http
.x509((x509) -> x509
.x509PrincipalExtractor(principalExtractor)
)
.authorizeHttpRequests((exchanges) -> exchanges
.anyRequest().authenticated()
);
return http.build();
}
@Bean
fun springSecurity(http: HttpSecurity): DefaultSecurityFilterChain? {
val principalExtractor = SubjectX500PrincipalExtractor()
principalExtractor.setExtractPrincipalNameFromEmail(true)
http {
authorizeHttpRequests {
authorize(anyRequest, authenticated)
}
x509 {
x509PrincipalExtractor = principalExtractor
}
}
return http.build()
}
<http>
<intercept-url pattern="/**" access="authenticated"/>
<x509 principal-extractor-ref="principalExtractor"/>
</http>
<b:bean id="principalExtractor"
class="org.springframework.security.web.authentication.preauth.x509.SubjectX500PrincipalExtractor"
p:extractPrincipalNameFromEmail="true"/>
在前面的示例中,使用者名稱是從客戶端證書的 emailAddress 欄位中提取的,而不是 CN,並且賬戶查詢使用自定義的 ReactiveAuthenticationManager 例項。
有關配置 Netty 和 WebClient 或 curl 命令列工具以使用相互 TLS 並啟用 X.509 認證的示例,請參閱 github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration/authentication/x509。
在 Tomcat 中設定 SSL
Spring Security 示例倉庫中有一些預先生成的證書。如果您不想生成自己的證書,可以使用它們來啟用 SSL 進行測試。server.jks 檔案包含伺服器證書、私鑰和頒發機構證書。還有一些客戶端證書檔案,用於示例應用程式中的使用者。您可以將這些證書安裝到瀏覽器中以啟用 SSL 客戶端認證。
要在 Tomcat 中執行 SSL 支援,請將 server.jks 檔案放入 Tomcat 的 conf 目錄,並在 server.xml 檔案中新增以下聯結器
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="${catalina.home}/conf/server.jks"
keystoreType="JKS" keystorePass="password"
truststoreFile="${catalina.home}/conf/server.jks"
truststoreType="JKS" truststorePass="password"
/>
如果即使客戶端未提供證書,您仍然希望 SSL 連線成功,clientAuth 也可以設定為 want。未提供證書的客戶端無法訪問任何受 Spring Security 保護的物件,除非您使用非 X.509 認證機制,例如表單認證。