GraalVM 原生镜像中的方法安全性
尽管 GraalVM 原生镜像支持方法安全性,但某些用例需要应用程序提供额外的提示。
使用 @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!";
}
|
请记住,您需要在配置类中添加 |
如果您运行具有上述配置的应用程序的原生镜像,当尝试调用 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 原生镜像默认不支持反射。
要解决此问题,您需要向 GraalVM 原生镜像提供提示,以允许对 CustomUserDetails#isAdmin() 方法进行反射。我们可以通过提供自定义提示来做到这一点。在此示例中,我们将使用 @RegisterReflectionForBinding 注解。
|
您可能需要注册所有您希望在 |
使用 @RegisterReflectionForBinding
@Configuration
@RegisterReflectionForBinding(CustomUserDetails.class)
public class MyConfiguration {
//...
}
就这样,现在您可以运行应用程序的原生镜像,它应该按预期工作。