我正在设置一个Spring Boot(v1.2.6)Web项目并使用Spring Security(v3.2.8)。我发现@PreAuthorize
注释非常方便,但是我不知道是否有办法从注释中的SpEL读取Boot的属性。我正在尝试这样做:
@PreAuthorize
使用在[[application.yml中声明的属性:
@PreAuthorize("mysecurity.permit")
但是我得到
mysecurity: permit: true
我也尝试过Failed to evaluate expression 'mysecurity.permit'
和@mysecurity.permit
,结果相同。在服务中声明一个方法并以${mysecurity.permit}
的方式访问它似乎是可能的,但是我很高兴知道我是否能够直接访问该属性。
[如果您查看OnExpressionCondition实现,您会注意到它获得了传递给注释的值,在您的注释中链接的情况下,类似于@service.isMySecurityPermited()
注释只是获取了文本值,不知道文字代表什么,只知道它是一个字符串。正是在OnExpressionCondition中注释值的处理中,字符串值才有意义。他们采用String值,并将其传递给BeanExpressionResolver进行解析。
因此,在基于@ConditionalOnExpression("${server.host==localhost} or ${server.port==8080} ")
的PreAuthorize解决方案中,该解决方案还将其传递给表达式处理器,您应该能够使用spring的表达式语言来引用任何bean属性。
我目前无法进行测试,但是从该线程看来,您可以做类似的事情
@Component
public class MyBean {
@Value("${mysecurity.permit}")
private Boolean permit;
public boolean isPermitted() { return permit; }
@PreAuthorize( "@myBean.isPermitted()" )
public blah myMethod() {
// do stuff
}
}
然后使用:
@Value("${mysecurity.permit}") private Boolean permit;
但是您需要正确设置配置文件,以允许Spring访问它。在这里阅读:@PreAuthorize(permit)
UPDATE:您是否为属性占位符配置了bean?例如:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
这可能是评估我想与您共享的表达式的通用方法:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:com/foo/app.properties</value>
</list>
</property>
</bean>
并且在yaml配置文件中,您可以配置路径和授权表达式,类似这样:
@Component("AuthorizationComponent")
public final class AuthorizationComponent {
private final static Logger logger = Logger.getLogger(AuthenticationUtils.class.getName());
private static SpelExpressionParser parser;
static {
parser = new SpelExpressionParser();
}
@Autowired
private Environment environment;
public boolean evaluateExpression(final String propertyKey) {
return checkExpression(environment.getProperty(propertyKey));
}
public static boolean checkExpression(String securityExpression) {
logger.info("Checking security expression [" + securityExpression + "]...");
SecurityContext securityContext = SecurityContextHolder.getContext();
Authentication authentication = securityContext.getAuthentication();
Expression exp = parser.parseExpression(securityExpression);
SecurityExpressionRoot context = new CustomMethodSecurityExpressionRoot(authentication);
boolean result = exp.getValue(context, Boolean.class);
logger.info("Check result: " + result);
return result;
}
}
然后您可以在您的方法中像这样使用它:
preAuthorize:
whatever:
post: hasRole('MY_ROLE') OR hasAuthority('MY_AUTHORITY')