Spring Security 6.3 の新機能

Spring Security 6.3 には、いくつかの新機能があります。以下はリリースのハイライトです。また、各機能とバグ修正の詳細なリストについては、リリースノート [GitHub] (英語) を参照してください。

パッシブ JDK 直列化サポート

JDK 直列化されたセキュリティコンポーネントのサポートに関しては、Spring Security は歴史的にかなり積極的で、各直列化バージョンを 1 つの Spring Security マイナーバージョンのみでサポートしていました。つまり、JDK 直列化されたセキュリティコンポーネントがある場合、デシリアライズできなくなるため、次の Spring Security バージョンにアップグレードする前に退避する必要がありました。

現在、Spring Security は 6 か月ごとにマイナーリリースを実行しているため、これは大きな問題点となっています。これに対処するために、Spring Security は JSON 直列化と同様に JDK 直列化でも受動性を維持し (英語) 、よりシームレスなアップグレードを実現します。

認可

過去数回のリリースで継続中のテーマは、Spring Security の認証サブシステムのリファクタリングと改善です。AccessDecisionManager API を AuthorizationManager に置き換えることから始まり、今ではいくつかのエキサイティングな新機能を追加できるようになりました。

アノテーションパラメーター - #14480 [GitHub] (英語)

6.3 の最初の機能は、アノテーションパラメーターのサポート [GitHub] (英語) です。次のような 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 [GitHub] (英語) , #14597 [GitHub] (英語)

Spring Security の初期の頃から、Spring Bean に @PreAuthorize と @PostAuthorize のアノテーションを付けることができました。しかし、コントローラー、サービス、リポジトリだけがセキュリティ保護の対象ではありません。たとえば、管理者だけが Order#getPayment メソッドを呼び出せるようにするドメインオブジェクト Order はどうでしょうか。

現在、6.3 では、これらのメソッドにもアノテーションを付けることができます [GitHub] (英語) 。まず、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 インスタンスをプロキシする [GitHub] (英語) ことによって、findOrderById から返された Order を保護します。

エラー処理 - #14598 [GitHub] (英語) , #14600 [GitHub] (英語) , #14601 [GitHub] (英語)

このリリースでは、最新の新しいメソッドセキュリティアノテーションを使用して、メソッドレベルで障害をインターセプトして処理する [GitHub] (英語) こともできます。

  • 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 データサンプル [GitHub] (英語) で確認できます。

侵害されたパスワードのチェック - #7395 [GitHub] (英語)

ユーザーにパスワードを選択させる場合は、そのパスワードがすでに侵害されていないことを確認することが重要です。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 [GitHub] (英語) の一部です

2017 年以来、Spring Security はさまざまな Spring Security 拡張機能を Spring Security 本体に組み込むという長期的な取り組みを進めてきました。6.3 では、spring-security-rsa がこれらのプロジェクトの最新版となり、チームが長期的に維持し、機能を追加できます。

OAuth 2.0 トークン交換許可 - #5199 [GitHub] (英語)

Spring Security で最も投票数が多かった OAuth 2.0 機能 [GitHub] (英語) の 1 つが、6.3 に導入されました。これは、OAuth 2.0 トークン交換許可 [IETF] (英語) のサポートです。

トークン交換用に設定されたクライアントの場合は、次のように TokenExchangeAuthorizedClientProvider インスタンスを OAuth2AuthorizedClientManager に追加することで、Spring Security でアクティブ化できます。

  • Java

  • Kotlin

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

その後、通常どおり @RegisteredOAuth2AuthorizedClient アノテーションを使用して、リソースサーバーに必要な拡張された権限を持つ適切なトークンを取得します。

その他のハイライト

完全なリストについては、6.3.0-RC1 [GitHub] (英語) 6.3.0-M3 [GitHub] (英語) 6.3.0-M2 [GitHub] (英語) 6.3.0-M1 [GitHub] (英語) のリリースノートを参照してください。