Spring Security 6.3 新功能

Spring Security 6.3 提供許多新功能。以下是此版本的重點,或者您可以檢視發行說明,以取得每個功能和錯誤修復的詳細列表。

被動式 JDK 序列化支援

在支援 JDK 序列化的安全組件方面,Spring Security 歷史上一直相當積極,每個序列化版本僅支援一個 Spring Security 次要版本。這表示如果您有 JDK 序列化的安全組件,則在升級到下一個 Spring Security 版本之前,需要先撤離這些組件,因為它們將不再可反序列化。

現在 Spring Security 每六個月執行一次次要版本發布,這已成為一個更大的痛點。為了解決這個問題,Spring Security 現在將維持對 JDK 序列化的被動性,就像對 JSON 序列化一樣,從而實現更無縫的升級。

授權

最近幾個版本的持續主題一直是重構和改進 Spring Security 的授權子系統。從將 AccessDecisionManager API 替換為 AuthorizationManager 開始,現在已經到了我們可以添加幾個令人興奮的新功能的階段。

註解參數 - #14480

6.3 的第一個功能是支援註解參數。考慮 Spring Security 對元註解的支援,例如這個

  • Java

  • Kotlin

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@PreAuthorize("hasAuthority('SCOPE_message:read')")
public @interface HasMessageRead {}
Kotlin
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@PreAuthorize("hasAuthority('SCOPE_message:read')")
annotation class HasMessageRead

在此版本之前,只有在程式碼庫中廣泛使用類似的東西時,它才有用。但現在,您可以像這樣添加參數

  • Java

  • Kotlin

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@PreAuthorize("hasAuthority('SCOPE_{scope}')")
public @interface HasScope {
	String scope();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@PreAuthorize("hasAuthority('SCOPE_{scope}')")
annotation class HasScope (val scope:String)

使其可以執行像這樣的操作

  • Java

  • Kotlin

@HasScope("message:read")
public String method() { ... }
@HasScope("message:read")
fun method(): String { ... }

並在更多地方應用您的 SpEL 表達式。

安全傳回值 - #14596#14597

自 Spring Security 早期以來,您就可以使用 @PreAuthorize@PostAuthorize 註解 Spring bean。但是控制器、服務和儲存庫並不是您唯一關心安全性的東西。例如,如果有一個網域物件 Order,只有管理員才能呼叫 Order#getPayment 方法呢?

現在在 6.3 中,您也可以註解這些方法。首先,像註解 Spring bean 一樣註解 getPayment 方法

  • Java

  • Kotlin

public class Order {

	@HasScope("payment:read")
	Payment getPayment() { ... }

}
class Order {

	@HasScope("payment:read")
	fun getPayment(): Payment { ... }

}
  • Java

  • Kotlin

public interface OrderRepository implements CrudRepository<Order, String> {

	@AuthorizeReturnObject
	Optional<Order> findOrderById(String id);

}
interface OrderRepository : CrudRepository<Order, String> {
    @AuthorizeReturnObject
    fun findOrderById(id: String?): Optional<Order?>?
}

屆時,Spring Security 將透過代理 Order 實例來保護從 findOrderById 傳回的任何 Order

錯誤處理 - #14598#14600#14601

在此版本中,您還可以透過其最後一個新的方法安全註解,在方法層級攔截和處理失敗

當您像這樣使用 @HandleAuthorizationDenied 註解方法

  • Java

  • Kotlin

public class Payment {
    @HandleAuthorizationDenied(handlerClass=Mask.class)
    @PreAuthorize("hasAuthority('card:read')")
    public String getCreditCardNumber() { ... }
}
class Payment {
    @HandleAuthorizationDenied(handlerClass=Mask.class)
    @PreAuthorize("hasAuthority('card:read')")
    fun getCreditCardNumber(): String { ... }
}

並發布一個 Mask bean

  • Java

  • Kotlin

@Component
public class Mask implements MethodAuthorizationDeniedHandler {
	@Override
    public Object handleDeniedInvocation(MethodInvocation invocation, AuthorizationResult result) {
		return "***";
    }
}
@Component
class Mask : MethodAuthorizationDeniedHandler {
    fun handleDeniedInvocation(invocation: MethodInvocation?, result: AuthorizationResult?): Any = "***"
}

那麼任何未經授權呼叫 Payment#getCreditCardNumber 都將傳回 *** 而不是號碼。

您可以在最新的 Spring Security Data 範例中看到所有這些功能一起運作。

洩漏密碼檢查 - #7395

如果您要讓使用者選擇密碼,那麼確保此密碼尚未洩漏至關重要。Spring Security 6.3 使此操作變得非常簡單,只需發布一個 CompromisedPasswordChecker bean即可

  • Java

  • Kotlin

@Bean
public CompromisedPasswordChecker compromisedPasswordChecker() {
    return new HaveIBeenPwnedRestApiPasswordChecker();
}
@Bean
fun compromisedPasswordChecker(): CompromisedPasswordChecker = HaveIBeenPwnedRestApiPasswordChecker()

spring-security-rsa 現在是 Spring Security 的一部分 - #14202

自 2017 年以來,Spring Security 一直在進行一項長期計畫,將各種 Spring Security 擴充功能整合到 Spring Security 本身中。在 6.3 中,spring-security-rsa 成為這些專案中的最新一個,這將有助於團隊長期維護並為其添加功能。

spring-security-rsa 提供了許多方便的 BytesEncryptor 實作,以及一個更簡單的 API 用於處理 KeyStores

OAuth 2.0 令牌交換授權 - #5199

對於任何配置為令牌交換的用戶端,您可以透過將 TokenExchangeAuthorizedClientProvider 實例添加到您的 OAuth2AuthorizedClientManager 中,在 Spring Security 中啟動它,如下所示

  • Java

  • Kotlin

@Bean
public OAuth2AuthorizedClientProvider tokenExchange() {
	return new TokenExchangeOAuth2AuthorizedClientProvider();
}
@Bean
fun tokenExchange(): OAuth2AuthorizedClientProvider = TokenExchangeOAuth2AuthorizedClientProvider()

然後像往常一樣使用 @RegisteredOAuth2AuthorizedClient 註解來檢索具有資源伺服器所需的擴展權限的適當令牌。

其他重點

  • gh-14655 - 新增 DelegatingAuthenticationConverter

  • gh-6192 - 在 WebFlux 上新增並行 Session 控制 (文件)

  • gh-14193 - 新增對 CAS Gateway 身份驗證的支援

  • gh-13259 - 自訂何時呼叫 UserInfo

  • gh-14168 - 在 OAuth2AuthorizationRequestRedirectFilter 中引入可自訂的 AuthorizationFailureHandler

  • gh-14672 - 自訂從 OidcUserRequest 和 OidcUserInfo 映射 OidcUser

  • gh-13763 - 簡化反應式 OAuth2 用戶端組件模型的配置

  • gh-14758 - 使用範例更新反應式 OAuth2 文件登陸頁面 (文件)

  • gh-10538 - 支援憑證綁定的 JWT 存取令牌驗證

  • gh-14265 - 支援 UserInfo 回應中的巢狀使用者名稱

  • gh-14449 - 新增 SecurityContext 參數解析器

  • gh-11440 - 簡化停用 application/x-www-form-urlencoded 編碼用戶端 ID 和密碼 (servlet 文件, reactive 文件)

如需詳盡列表,請參閱發行說明 6.3.0-RC16.3.0-M36.3.0-M26.3.0-M1