我想使用@PreAuthorize注释来保护Spring REST控制器中的方法,使用方法参数,例如
@RequestMapping("/something/{myParam}")
@PreAuthorize("@security.check(#myParam)")
public String getSomething(@PathVariable("myParam") Integer myParam) {
//...
}
Spring Security需要一种在运行时发现param名称的方法。当编译类中没有调试符号时,需要添加一个特殊的注释@P或Spring Data的@Param。所以,这个方法看起来像这样:
@RequestMapping("/something/{myParam}")
@PreAuthorize("@security.check(#myParam)")
public String getSomething(@PathVariable("myParam") @P("myParam) Integer myParam) {
//...
}
是否有可能以某种方式暗示Spring Security使用@PathVariable而避免使用@P等其他注释?
根据the documentation,注释中的参数名称由AnnotationParameterNameDiscoverer
完成,可以自定义以支持任何指定注释的value属性。但是,我找不到有关如何自定义的任何信息。
顺便说一下,我使用的是Java 7和Spring Security 3.2.9。
答案 0 :(得分:5)
简而言之,您需要在方法SecurityExpressionHandler
中覆盖GlobalMethodSecurityConfiguration#createExpressionHandler
的创建,以便在自定义ParameterNameDiscoverer
中设置您自己的GlobalMethodSecurityConfiguration
。
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
@Autowired
private ApplicationContext context;
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler result = new DefaultMethodSecurityExpressionHandler();
result.setApplicationContext(this.context);
result.setParameterNameDiscoverer(new AnnotationParameterNameDiscoverer(PathVariable.class.getName()));
return result;
}
}
在sample project中,您可以在控制台输出中看到类似这样的结果
2016-06-06 17:09:01.635 INFO 2871 --- [nio-8080-exec-4] c.s.so.q37435824.SecurityService: myParam value from PathVariable equals 1
祝你好运
答案 1 :(得分:2)
以下配置未经过测试,但基于sources of spring security的研究,请尝试按如下方式更改Spring Security配置xml
<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="parameterNameDiscoverer" ref="parameterNameDiscoverer"/>
</bean>
<bean id="parameterNameDiscoverer" class="org.springframework.security.core.parameters.AnnotationParameterNameDiscoverer">
<constructor-arg>
<list>
<value>org.springframework.web.bind.annotation.PathVariable</value>
</list>
</constructor-arg>
</bean>
答案 2 :(得分:2)
来自官方的Spring安全文档GlobalMethodSecurityConfiguration
有时您可能需要执行更复杂的操作 比
@EnableGlobalMethodSecurity
注释更可能 允许。对于这些实例,您可以扩展GlobalMethodSecurityConfiguration
确保 您的子类上存在@EnableGlobalMethodSecurity
注释。 例如,如果要提供自定义MethodSecurityExpressionHandler
,您可以使用以下内容 配置:
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
// ... create and return custom MethodSecurityExpressionHandler ...
return expressionHandler;
}
}
如上例所示,您可以编写自定义MethodSecurityExpressionHandler
或使用DefaultMethodSecurityExpressionHandler
和set自定义ParameterNameDiscoverer扩展DefaultSecurityParameterNameDiscoverer(或不)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setParameterNameDiscoverer(new CustomParameterNameDiscoverer());
return expressionHandler;
}
}
又一个例子Spring Security Java Config Preview: Custom Method Security
希望这有帮助。
答案 3 :(得分:0)
从Spring安全官员documentation可以实现所请求的用例。但要使用你需要升级到弹簧4.1.0,我没试过看起来这是可以实现的