GraalVM Native Image 中的方法安全性
雖然 GraalVM Native Image 支援方法安全性,但有些使用案例需要應用程式提供額外的提示。
使用 @PreAuthorize
和 @PostAuthorize
註解
如果您有 UserDetails
或 Authentication
類別的自訂實作,則使用 @PreAuthorize
和 @PostAuthorize
註解需要額外的提示。
讓我們舉一個範例,您有一個 UserDetails
類別的自訂實作如下,並且該實作是由您的 UserDetailsService
回傳
UserDetails 的自訂實作
public class CustomUserDetails implements UserDetails {
private final String username;
private final String password;
private final Collection<? extends GrantedAuthority> authorities;
public boolean isAdmin() {
return this.authorities.contains(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
// constructors, getters and setters
}
並且您想要在 @PreAuthorize
註解內使用 isAdmin()
方法,如下所示
使用 isAdmin() 來保護方法
@PreAuthorize("principal?.isAdmin()")
public String hello() {
return "Hello!";
}
請記住,您需要將 |
如果您執行應用程式的 native image 與上述組態,當嘗試叫用 hello()
方法時,您將會收到類似以下的錯誤
failed: java.lang.IllegalArgumentException: Failed to evaluate expression 'principal?.isAdmin()' with root cause
org.springframework.expression.spel.SpelEvaluationException: EL1004E: Method call: Method isAdmin() cannot be found on type com.mypackage.CustomUserDetails
這表示在 CustomUserDetails
類別上找不到 isAdmin()
方法。這是因為 Spring Security 使用反射來叫用 isAdmin()
方法,而 GraalVM Native Image 預設不支援反射。
若要修正此問題,您需要給予 GraalVM Native Image 提示,以允許在 CustomUserDetails#isAdmin()
方法上進行反射。我們可以透過提供自訂提示來做到這一點。在本範例中,我們將使用@RegisterReflectionForBinding
註解。
您可能需要註冊所有您想要在 |
使用 @RegisterReflectionForBinding
@Configuration
@RegisterReflectionForBinding(CustomUserDetails.class)
public class MyConfiguration {
//...
}
就是這樣,現在您可以執行應用程式的 native image,它應該可以如預期般運作。