如何为 Spring Security 创建类型安全的用户角色?
Posted
技术标签:
【中文标题】如何为 Spring Security 创建类型安全的用户角色?【英文标题】:How to create typesafe user roles for Spring Security? 【发布时间】:2014-07-01 01:25:03 【问题描述】:我想将spring-security
与ROLE_ADMIN
和ROLE_USER
角色一起使用。
因此我尝试创建一个类型安全的枚举类,但 @Secured
注释需要一个常量 String
,而我无法通过使用枚举类来实现。
我可以在以下代码中进行哪些更改?
public enum UserRole
ADMIN("ROLE_ADMIN");
private String role;
public UserRole(String role)
this.role = role;
//error: The value for annotation attribute Secured.value must be a constant expression
@Secured(USerRole.ADMIN.value())
public class SecuredView
【问题讨论】:
为什么不创建一个字符串类型的常量? 也许也看到这个答案:***.com/questions/19303584/… 【参考方案1】:这个问题有点老了,但这是我的看法:
public enum Role implements GrantedAuthority
ROLE_USER, ROLE_ADMIN;
@Override
public String getAuthority()
return name();
然后您可以将它与 @PreAuthorize 和 Spring Expression Language 一起使用来授权您的方法和类,如下所示:
@PreAuthorize("hasRole(T(<package name>.Role).ROLE_ADMIN)")
public void doSomeThing()
...
注意:包名必须是完整的包名(org.company.project),并且不带。
如您所见,根据定义,这不是类型安全的,因为 SpEL 表达式仍然是字符串,但 IntelliJ 等 IDE 可以识别它们,并且会通知您任何错误。
您可以使用 hasAnyRole() 将 @PreAuthorize 与多个角色一起使用。
当然,对于许多角色,这可能会变得有点冗长,但您可以通过创建自己的注释来使其更漂亮,如下所示:
@Target( ElementType.METHOD, ElementType.TYPE )
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@PreAuthorize("hasRole(T(<package name>.Role).ROLE_ADMIN)")
public @interface AdminAuthorization
之后,您可以像这样授权您的方法:
@AdminAuthorization
public void doSomething()
...
【讨论】:
我想问一个关于答案的问题。我在答案中使用了解决方案。我想问什么;如何在层次结构中应用枚举类型。例如,ROLE_ADMIN> ROLE_USER @forguta 这不是很漂亮,但你可以用@PreAuthorize("hasAnyRole(T(<package name>.Role).ROLE_ADMIN, T(<package name>.Role).ROLE_USER)")
注释你的@AdminAuthorization
注释【参考方案2】:
部分解决方案:
public enum Role implements GrantedAuthority
ADMIN(Code.ADMIN),
USER(Code.USER);
private final String authority;
Role(String authority)
this.authority = authority;
@Override
public String getAuthority()
return authority;
public class Code
public static final String ADMIN = "ROLE_ADMIN";
public static final String USER = "ROLE_USER";
结果:
@Secured(Role.Code.ADMIN)
【讨论】:
IMO,这绝对是最“类型安全”的解决方案,因为其他提议的选项传递了“hasRole('MY_ROLE')”字符串,我几乎不会认为它是类型安全的。跨度> 【参考方案3】:如果您使用的是 Lombok,则可以使用 @FieldNameConstants 注释:
@FieldNameConstants
public class UserRoles
private String ROLE_USER, ROLE_ADMIN;
然后像这样使用它:
@Secured(UserRoles.Fields.ROLE_ADMIN)
也许以后会有@EnumNameConstants注解,会更合适。
【讨论】:
以上是关于如何为 Spring Security 创建类型安全的用户角色?的主要内容,如果未能解决你的问题,请参考以下文章
如何为具有 Spring Security 配置的 Spring Boot API 编写单元测试
如何为登录GRAILS(Spring security)的用户实现会话?
如何为密钥持有者配置文件配置 Spring Security SAML 扩展
如何为 Webflux、Spring-Security、okta-spring-boot-starter 和 Okta-React 正确使用 CORS?