Is it possible to add a spring interceptor in a spring security filter chain? - spring

I need to retrieve the path param map in my spring boot application and I noticed that the following line of code:
final Map<String, String> pathVariables = (Map<String, String>) request
.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
only works when in a spring boot InterceptorHandler class, I guess because the "path param" abstraction is spring's.
Problem is that I'm using spring security, defining my own filter chain:
http.addFilterBefore(...).addFilterAfter(myFilterNeedingPathParam) //series of filters
And the last filter needs the path params map. My idea would be to put the interceptor before or, if you want, make sure that the last filter is executed after.
Is there a way to do so?

When in the Spring InterceptorHandler, check the actual class of the request, you may need to cast your request to that. Also look into the source code for that class and see if it's pulling that value from a ThreadLocal of some sort.

Related

How can I set http method in servlet filter(in context of Spring Framework)?

I have got a such issue: I do have got antMatcher​ in Spring Security. And I have an opportunity to set http method GET/POST/PUT/PATCH/DELETE for url mapping for my filter. So requests with some methods will be filtered with my filter if they have certain methods and will not be filtered otherways. But how can I specify http method without Spring Security? Is it possible to do it somehow in a cool way using FilterRegistrationBean or I will be have to use
switch(request.getMethod()) {
...
}
in my fileter doFilterInternal() method (I use OncePerRequestFilter) and act according to which method is specified in HttpServletRequest? That is tedious, isn`t it?
I tried to find out some info according to this issue and researches have not been successful yet.
#Bean
public FilterRegistrationBean<CustomFilter> registrationBean(){
FilterRegistrationBean<CustomFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(customFilter);
registration.addUrlPatterns("/open/*");
/*may be it is possible to addHttpMethods?*/
registration.setName("customLoggingFilter");
registration.setOrder(2);
return registration;
}
Well, no. It is impossible, but I was told that it is a really not bad idea to override the shouldFilter method of the OncePerRequestFilter.

Spring Interceptor and AuthenticationFilter Order of Execution

I have a LoginHandler and an Interceptor. I want the Interceptor to execute before the AuthenticationFilter. Is there a way to specify the order of execution?
UPDATED:
The title mentioned LoginHandler. I changed it to AuthenticationFilter.
A HandlerInterceptor from Spring will never execute before a filter.
The javax.servlet.Filter is part of the Java Servlet API and requests always first pass through Filter instances, before reaching a Servlet.
HandlerInterceptor instances are executed as part of the request handling inside the DispatcherServlet (which implements javax.servlet.Servlet). As mentioned the flow is Filter -> Servlet the result is that a HandlerInterceptor will always execute after a Filter.
So is what you want possible, no it isn't. No matter how much ordering you add to the HandlerInterceptor.

How to get the original handler URI (with wildcards, etc.) in a HandlerInterceptor in Spring?

I am collecting custom metrics for my controller endpoints via HandlerInterceptor. In postHandle I have everything I need and I would like to save the metrics for my endpoints along with the original route defined in the controller, so not the actual route filled with the data.
E.g. I have #GetMapping("/cats/{name}") and make GET request on /cats/tom I still want the defined route "cats/{name}"
I found that I can do this with the Object handler which is the parameter of postHandle -> I can cast it to HandlerMethod get the annotations of the method and find it from memberValues. This seems a bit overkill I also have to filter for Get-, Post-, Put-, Delete-, Patch-, RequestMapping annotations. Is there any easier or more straightforward way to do this? If so how? If not what else do I have to take into consideration with this solution?
It turns out Spring adds this data to the HttpServletRequest attributes. So it can be retrieved using:
String routePattern = (String) request.getAttribute("org.springframework.web.servlet.HandlerMapping.bestMatchingPattern");

Parsing a POJO to JSON using JAX-RS and not using any speific implemnation code

I was looking at internals of jersey, on how it converts a simple POJO to Json. Jersey has an interface Providers, which will provide list of contextResolvers given the class and mediaType. once we get the contextResolver, we can get the Context and Marshaller from it, which can used to get the json string, like show below.
lets assume we want to serialize the Pojo "obj". the code will look like follows
Providers ps = ...
ContextResolver<JAXBContext> resolver = ps.getContextResolver(obj.getClass(), MediaType.APPLICATION_JSON_TYPE);
JAXBContext ctx = resolver.getContext(obj.getClass());
ctx.createMarshaller().marshal(obj, writer);
By above way we can convery any POJO which has a valid context resolver to json. but the question is how do we get the handler for Providers.
PS: i have not compiled this code, but from what i can see from source this is what jersey does. On why i am doing all this stuff, so that we can convert a object to JSON directly with JAX-RS apis. instead of using any implementation code.
In a JAX-RS resource clas, use the #Context annotation to tell Jersey to inject the producers:
#Context Producers producers;
So your question is : "how to find providers" ?
You have to write code to find classes in the classpath which are Annotated with #Provider.

Spring boot actuator - Implement custom metrics

I would like to implement custom metric or statistics to my spring boot rest web service using actuator but i am not able to find simple tutorials.
For example:
how to show how many times a certain controller was called and what exact parameter field was filled?
how can i create a metric that when its URL is called, it runs certain query and shows back a json with some result
This seems like a good scenario for AOP (Aspect Oriented Programing) as this will allow you to separate this statistic logic from the business logic.
Have a look at Spring doc for more info about AOP and how to achieve that with Spring.
You can then define a pointcut on your controller and have a service for counting (and probably then storing) the data.
Refer below link
AOP Example
For point two the solution is to create an endpoint class (it can be or not a rest controller class). For example:
#Component
#RestControllerEndpoint(id = "pfm-statistics")
public class StatisticsEndpoint {
#GetMapping(value = "/", produces = "application/vnd.openxmlformats-
officedocument.spreadsheetml.sheet")
#ResponseBody
public byte[] generateStatisticsAsExcel() {
...
Note that the ID is the path to be called from URL. We can create a simple endpoint too and just return a string if we want. In this case instead of #RestControllerEndpoint annotation we can use #Endpoint, as a side note, the id should always contain dash

Resources