如何使用@PathVariable解析Spring Security中的参数名称?

时间:2016-05-25 11:31:17

标签: java spring spring-mvc spring-security

我想使用@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。

4 个答案:

答案 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或使用DefaultMethodSecurityExpressionHandlerset自定义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,我没试过看起来这是可以实现的