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

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.

Related

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

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.

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 implement request timeout management in an AOP way in Spring Boot

currently I'm exploring approaches to implement 'request timeout management in an AOP way in Spring Boot' with several restrictions. The requirements/restrictions are stated as below:
The original purpose is that if the processing time of an api request exceeds 5 seconds, then directly return timeout result instead of continue processing
The rest api to be monitored is implemented by standard spring mvc rest controller. All apis inside are returning json strings like this:
#RestController
public class xxxxxx {
#RequestMapping(value = "xxxxxxx")
public String xxxxxx(#RequestParam(value = "xxxx", required = true) String xxxx) {
....
return json.toString();
}
}
The timeout logic is required to be implemented by AOP
(The real mean part)
No changes should be made to the controllers, which means: Request generation approach should not be changed; Return type should not be changed(No 'Callable<...>' allowed)
I have already found 1 answer(Async approach) which can perfectly resolve the problem itself with spring async, and the timeout return result is very pretty, but it's changing the return type, and also touching the code in controller. I also found one solution(AOP approach) which is using AOP, but the scenario is quite different from mine. It's already moving some business logic into AOP class, but I'm not allowed to touch the controller code. I would be grateful if anyone can provide a solution. Solutions that can't meet all the restrictions but are minimizing the differences are also admitted.
Since there is still no response to this question, I will put my own temporary solution here.
I'm using Hystrix dependency.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
It's well integrated with springboot, so the configuration is easy. Once properly configured, need to append an annotation on the request method that requires timeout handling. e.g.
#HystrixCommand(fallbackMethod="fallback")
#RequestMapping(value = "xxxxxxx")
public String xxxxxx(#RequestParam(value = "xxxx", required = true) String xxxx) {
....
return json.toString();
}
And need to add a fallback method with the name mapped to the value of 'fallbackMethod' inside annotation:
public String fallback() {
...
}
The timeout time value can be globally configured inside application.properties
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=3000
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=3000
This is still not concise in these points:
Need to copy/paste this annotation for every method
Need to copy/paste the fallback method in every place hystrix is used
For hystrix fallback method itself, the parameter type and number need to be exactly same with the hystrix marked method. Currently I'm using several overloading method called 'fallback' for this, in each controller
But at least it's not changing method return types and code inside methods anymore and is the best solution I can think of currently. Will perform update once I find better solutions.

Good idea using ControllerAdvice to perform REST authentication of a request?

In my current Spring Boot application i seem to hit a wall when trying to implement a REST request filter. My goal with the request filter was to read the header and body part and validate the incoming data and check if it meets the HMAC construction we are using.
So the request filter seemed not to work an alternative solutions is to use #ControllerAdvice.
Then the request validation can be implemented very easy. But i am not sure if it normally seen as an incorrect usage of the #ControllerAdvice annotation.
#ControllerAdvice
public class GenericWebControllerAdvice {
#ModelAttribute
public void authenticationFilter(#RequestHeader(value = "Authorization") String authHeader, #RequestBody String payload) {
// process authentication based on header info and body content
// calculate the hash and check if meets the security settings
// if the hash fails throw an exception that returns a http status code
}
}
Any comments on the solution or alternatives that are better?
No you should do the validation in the controller (ie method with #RequestMapping).
Spring supports JSR 303/349 bean validation. Thus if your request body is a POJO and you have the correct annotation Spring will automatically do the validation for you. There is a tutorial of that here:
http://www.leveluplunch.com/java/tutorials/017-validate-spring-rest-webservice-request/
As for request parameter validation (ie not bean validation) I have had to make my own transfer objects and exception handling. How you do global exception handling is covered in the Spring Reference guide but generally you extend and/or register a org.springframework.web.servlet.handler.SimpleMappingExceptionResolver. Ironically #ControllerAdvice can be used for exception handling but I find it better to extend and register an Exception Resolver. More info can be found here:
https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-exceptionhandlers
Edit based on OP comments and edits:
If your doing authentication or some other request based validation/authorization its probably best to use an Interceptor. Reference doc. #ControllerAdvice will probably not work as the request handling is too far a long. That is you want something before databinding happens.

Spring 3, ReST, #ResponseBody and #ExceptionHandler

I have been trying to get exception handling working in my simple Spring 3 based ReST web services. Based on everything I have seen, there is a bug that prevents this from working automatically with the #ResponseBody and #ExceptionHandler annotations
https://jira.springsource.org/browse/SPR-6902
So given that it isn't supported until Spring 3.1 or 3.0.6, what is the current best method for doing exception handling? I have seen numerous posts but haven't found a clear answer that has worked for me. An ideal solution would be one that automatically provides support for both xml and json
Do I have to manually define the entire marshalling setup? Won't this remove the need for the annotations that make using Spring 3 rest support worth it?
Seems in order to manually define marshalling (i.e. Jaxb2Marshaller) I need to add a new dependency on spring-ws which is a bit of a pain
Is it easier to just define a 'Response' object that all my methods return and wrap all functions in try/catch blocks?
You can redirect on error and then return something in #ResponseBody:
#ExceptionHandler(Exception.class)
public ModelAndView handleMyException(Exception exception) {
return new ModelAndView("redirect:errorMessage?error="+exception.getMessage());
}
#RequestMapping(value="/errorMessage", method=RequestMethod.GET)
#Responsebody
public String handleMyExceptionOnRedirect(#RequestParameter("error") String error) {
return error;
}
Little ugly, but this is just work around till the fix will be available.
This is a good workaround, but with one addition. The #ExceptionHandler(Exception.class)
should be #ExceptionHandler(MyException.class, YourException.class) as you can get into a loop using the general Exception class.
You can then test for (ex instanceof Myexception) to determine the message to display if need be.

Resources