4

is there a way to access the httpRequest within a controller level @PreAuthorize annotation to obtain a PathVariable and use it for the expression inside the @PreAuthorize annotation?

I want to be able to do the following, where #somePathVariable would result in the actual value passed for the PathVariable:

@RequestMapping(value = "/{somePathVariable}/something")
@PreAuthorize("@someBean.test(#somePathVariable)")
public class SomeController { ... }

It also would be sufficient if i could access the HttpServletRequest and get the PathVariable manually.

Please note that this expression is at the controller level before answering. I'd appreciate any help!

Tommy Schmidt
  • 1,224
  • 1
  • 16
  • 30
  • you can add HttpServletRequest to any method in your controller. Spring will inject that regardless of whether you already have another argument or not. – pvpkiran Mar 15 '18 at 10:29
  • 2
    @pvpkiran, yes, but he doesn't want to do it. He needs a controller-level support, not method-level. – M. Prokhorov Mar 15 '18 at 10:30
  • Just out of curiosity, what happens with these annotations right now? – M. Prokhorov Mar 15 '18 at 10:30
  • @M.Prokhorov i think null is passed to the test method right now – Tommy Schmidt Mar 15 '18 at 10:32
  • I missed the last part of your question. If you wish to do it, you have to make `@PreAuthorize` at method level. At class level you cannot get hold of HttpServletRequest. – pvpkiran Mar 15 '18 at 10:33
  • @pvpkiran hmm i already expected that. this would be a workaround for sure but would lead to a lot of duplicated PreAuthorize annotations in my controllers (one for each method..) – Tommy Schmidt Mar 15 '18 at 10:35
  • @M.Prokhorov just verified that null is passed instead of the actual PathVariable value – Tommy Schmidt Mar 15 '18 at 10:38
  • 1
    Your best option and probably the only one is to use `RequestMappingHandlerMapping`. Autowire this in some class, and create methods to extract the info you want. RequestMappingHandlerMapping has all the information about the rest endpoints mapping. – pvpkiran Mar 15 '18 at 11:01
  • @pvpkiran pretty good comment! I'll try that. Thanks – Tommy Schmidt Mar 15 '18 at 11:19

1 Answers1

3

So as @pvpkiran already commented. It's probably not possible to get the param the way i want. However his workaround with using a bean to access the PathVariables manually seems to work just fine.

@Component
@RequiredArgsConstructor
public class RequestHelper {
    private final HttpServletRequest httpServletRequest;

    /* https://stackoverflow.com/questions/12249721/spring-mvc-3-how-to-get-path-variable-in-an-interceptor/23468496#23468496 */
    public Object getPathVariableByName(String name) {
        final Map pathVariables = (Map) httpServletRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
        return pathVariables.get(name);
    }
}

and

@RequestMapping(value = "/{somePathVariable}/something")
@PreAuthorize("@someBean.test(@requestHelper.getPathVariableByName('somePathVariable'))")
public class SomeController { ... }

did the job. It's not perfect but it works. The other (prob. better) option is to use @PreAuthorize on method level.

Thanks for your help!

Tommy Schmidt
  • 1,224
  • 1
  • 16
  • 30