Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use @PathVariable to resolve parameter name in Spring Security?

I would like to use @PreAuthorize annotations to secure methods in Spring REST controller, using method parameters, e.g.

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

Spring Security needs a way to discover param names in runtime. When there is no debugging symbols in the compiled class, it is necessary to add a special annotation @P or Spring Data's @Param. So, the method would look like this:

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

Is it possible to somehow hint Spring Security to use @PathVariable instead and avoid additional annotations like @P?

According to the documentation reading parameter names from annotations is done by AnnotationParameterNameDiscoverer which can be customized to support the value attribute of any specified annotation. However, I could not find any information on how to customize it.

BTW, I'm using Java 7 and Spring Security 3.2.9.

like image 293
pkalinow Avatar asked May 25 '16 11:05

pkalinow


People also ask

What is the use of @PathVariable annotation in Spring boot?

The @PathVariable annotation is used to extract the value of the template variables and assign their value to a method variable. A Spring controller method to process above example is shown below; @RequestMapping("/users/{userid}", method=RequestMethod.

What does @PathVariable annotation do?

Simply put, the @PathVariable annotation can be used to handle template variables in the request URI mapping, and set them as method parameters.

What is the purpose of @PathVariable annotation in Spring MVC?

@PathVariable is a Spring annotation which indicates that a method parameter should be bound to a URI template variable. If the method parameter is Map<String, String> then the map is populated with all path variable names and values. It has the following optional elements: name - name of the path variable to bind to.

What is the difference between @PathVariable and @RequestParam annotation?

2) @RequestParam is more useful on a traditional web application where data is mostly passed in the query parameters while @PathVariable is more suitable for RESTful web services where URL contains values.


1 Answers

In short, you need to override creating of SecurityExpressionHandler in the method GlobalMethodSecurityConfiguration#createExpressionHandler so that set your own ParameterNameDiscoverer in 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;
  }

}

In the sample project you can see result in console output something like this

2016-06-06 17:09:01.635  INFO 2871 --- [nio-8080-exec-4] c.s.so.q37435824.SecurityService: myParam value from PathVariable equals 1

Best regards

like image 60
Roman Sandarkin Avatar answered Oct 01 '22 16:10

Roman Sandarkin