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
这意味着 isAdmin()
方法无法在 CustomUserDetails
类中找到。这是因为 Spring Security 使用反射来调用 isAdmin()
方法,而 GraalVM Native Image 默认不支持反射。
要修复此问题,您需要向 GraalVM Native Image 提供提示,以允许对 CustomUserDetails#isAdmin()
方法进行反射。我们可以通过提供 自定义提示 来实现。在此示例中,我们将使用 @RegisterReflectionForBinding
注解。
您可能需要注册要在 |
使用 @RegisterReflectionForBinding
@Configuration
@RegisterReflectionForBinding(CustomUserDetails.class)
public class MyConfiguration {
//...
}
就是这样,现在您可以运行应用程序的本机映像,它应该按预期工作。