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

pka*_*now 9 java spring spring-mvc spring-security

我想使用@PreAuthorize注释来保护Spring REST控制器中的方法,使用方法参数,例如

@RequestMapping("/something/{myParam}")
@PreAuthorize("@security.check(#myParam)")
public String getSomething(@PathVariable("myParam") Integer myParam) {
  //...
}
Run Code Online (Sandbox Code Playgroud)

Spring Security需要一种在运行时发现param名称的方法.当编译类中没有调试符号时,需要添加一个特殊的注释@P或Spring Data的@Param.所以,该方法看起来像这样:

@RequestMapping("/something/{myParam}")
@PreAuthorize("@security.check(#myParam)")
public String getSomething(@PathVariable("myParam") @P("myParam) Integer myParam) {
  //...
}
Run Code Online (Sandbox Code Playgroud)

是否有可能以某种方式暗示Spring Security使用@PathVariable而避免使用像@P这样的其他注释?

根据文档读取,注释中的参数名称AnnotationParameterNameDiscoverer 可以自定义以支持任何指定注释的value属性.但是,我找不到有关如何自定义它的任何信息.

顺便说一句,我使用的是Java 7和Spring Security 3.2.9.

小智 5

简而言之,您需要覆盖SecurityExpressionHandler在方法中创建,GlobalMethodSecurityConfiguration#createExpressionHandler以便ParameterNameDiscoverer在custom 中设置自己的方法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;
  }

}
Run Code Online (Sandbox Code Playgroud)

示例项目中,您可以看到控制台输出的结果是这样的

2016-06-06 17:09:01.635  INFO 2871 --- [nio-8080-exec-4] c.s.so.q37435824.SecurityService: myParam value from PathVariable equals 1
Run Code Online (Sandbox Code Playgroud)

最好的祝福


vza*_*llo 3

来自官方 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

如上面的示例所示,您可以编写自定义MethodSecurityExpressionHandler或使用DefaultMethodSecurityExpressionHandler设置扩展DefaultSecurityParameterNameDiscoverer的自定义ParameterNameDiscoverer(或不扩展)

@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setParameterNameDiscoverer(new CustomParameterNameDiscoverer());
        return expressionHandler;
    }
}
Run Code Online (Sandbox Code Playgroud)

Spring Security Java 配置预览的另一个示例:自定义方法安全性

希望这可以帮助。