对于最新的稳定版本,请使用 Spring Security 6.3.1Spring中文文档

对于最新的稳定版本,请使用 Spring Security 6.3.1Spring中文文档

尽管 GraalVM 本机映像支持方法安全性,但有些用例需要应用程序提供其他提示。Spring中文文档

使用和注释@PreAuthorize@PostAuthorize

如果您有 OR 类的自定义实现,则使用和注释需要其他提示。@PreAuthorize@PostAuthorizeUserDetailsAuthenticationSpring中文文档

让我们举个例子,你有一个类的自定义实现,如下所示,该实现由你的返回:UserDetailsUserDetailsServiceSpring中文文档

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
}

您希望在注释中使用该方法,如下所示:isAdmin()@PreAuthorizeSpring中文文档

使用 isAdmin() 保护方法
@PreAuthorize("principal?.isAdmin()")
public String hello() {
    return "Hello!";
}

请记住,您需要将@EnableMethodSecurity注释添加到配置类中,以启用方法安全性注释。Spring中文文档

如果使用上述配置运行应用程序的本机映像,则在尝试调用该方法时将收到类似于以下内容的错误:hello()Spring中文文档

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

这意味着在类上找不到该方法。 这是因为 Spring Security 使用反射来调用该方法,而 GraalVM Native Image 默认不支持反射。isAdmin()CustomUserDetailsisAdmin()Spring中文文档

要解决此问题,您需要向 GraalVM 本机映像提供提示,以允许对方法进行反思。 我们可以通过提供自定义提示来做到这一点。 在此示例中,我们将使用 @RegisterReflectionForBinding解。CustomUserDetails#isAdmin()Spring中文文档

您可能需要注册要在 和 批注中使用的所有类。@PreAuthorize@PostAuthorizeSpring中文文档

使用@RegisterReflectionForBinding
@Configuration
@RegisterReflectionForBinding(CustomUserDetails.class)
public class MyConfiguration {
    //...
}

就是这样,现在您可以运行应用程序的本机映像,它应该按预期工作。Spring中文文档

请记住,您需要将@EnableMethodSecurity注释添加到配置类中,以启用方法安全性注释。Spring中文文档

您可能需要注册要在 和 批注中使用的所有类。@PreAuthorize@PostAuthorizeSpring中文文档