尊敬的各位专家,
我正在使用 Spring Security 来访问控制我的 REST API。作为其中的一部分,我定义了一个包含我的角色的枚举。
@Component("AppConstants")
public class AppConstants {
public enum Role {ADMIN, SUPER_ADMIN, USER};
//this class contains app level String constants and other enums
}
我想在 PreAuthorize.hasRole 注释中使用此枚举来定义控制器中的访问控制。
@PreAuthorize("hasRole(@AppConstants.Role.ADMIN.name())")
但是,该表达式无法计算,但出现以下异常:
**java.lang.IllegalArgumentException: Failed to evaluate expression 'hasRole(@AppConstants.Role.ADMIN.name())'**
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:33)
at org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager.check(PreAuthorizeAuthorizationManager.java:68)
at org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager.check(PreAuthorizeAuthorizationManager.java:40)
at org.springframework.security.config.annotation.method.configuration.DeferringObservationAuthorizationManager.check(DeferringObservationAuthorizationManager.java:47)
at org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor.attemptAuthorization(AuthorizationManagerBeforeMethodInterceptor.java:252)
at org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor.invoke(AuthorizationManagerBeforeMethodInterceptor.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:702)
**Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'Role' cannot be found on object of type 'com.mycode.utils.AppConstants' - maybe not public or not valid?**
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:222)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:105)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:93)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:62)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:92)
at org.springframework.expression.spel.ast.MethodReference.getArguments(MethodReference.java:164)
at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:94)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:119)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:309)
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:30)
... 98 more
从“可能不公开或无效”中得到提示,我尝试为 Enum 的值提供公共 getter 方法,但这没有帮助。
我在这里缺少什么?
要解决此问题,请在
AppConstants
中创建静态方法来获取角色名称,然后在 @PreAuthorize
注释中使用这些方法。
更新
AppConstants
课程:
@Component("AppConstants")
public class AppConstants {
public enum Role {
ADMIN, SUPER_ADMIN, USER
}
public static String getRoleAdmin() {
return Role.ADMIN.name();
}
public static String getRoleSuperAdmin() {
return Role.SUPER_ADMIN.name();
}
public static String getRoleUser() {
return Role.USER.name();
}
}
使用
@PreAuthorize
中的静态方法:
@PreAuthorize("hasRole(T(com.mycode.utils.AppConstants).getRoleAdmin())")
public void yourMethod() {
// method implementation
}
它确保 SpEL 可以正确访问角色名称。