How to get HttpServletRequest and HttpServletResponse in SOAP interceptor in spring - java

I have a spring boot application with SOAP endpoints and an interceptor class which implements EndpointInterceptor.The problem is, there is no overridden methods available in this interface which have access to HttpServletRequest and HttpServletResponse.
My question is :
How can I get HttpServletRequest and HttpServletResponse objects whenever an API request comes using a SOAP interceptor (I saw many examples which is using WebMvcConfigurerAdapter and HandlerInterceptor but it is working only for Rest #Controller. In my case it is SOAP with #Endpoint and it is not calling the overridden methods).
If that is not possible , how can i get make this object from MessageContext since the handleRequest overridden method is having that parameter as show below
#Override
public boolean handleRequest(MessageContext messageContext,
Object endpoint) throws Exception {
LOG.info("Endpoint Request Handling");
return true;
}

Spring-ws has TransportContext class for storing the current underlying connection. You can access it via TransportContextHolder class statically in the code.
If you are sure that the underlying connection is a HttpServletConnection then you could do something like this inside the interceptor methods:
TransportContext ctx = TransportContextHolder.getTransportContext();
HttpServletRequest req = ((HttpServletConnection) ctx.getConnection()).getHttpServletRequest();

If you want to manipulate (Override) the HttpServletRequest and HttpServletResponse
before/after reaching the endpoints using Interceptors would be a bad idea as the requests reached at that level would be preprocessed and would not give you the option of modification.
You could use Filters instead of Interceptors to achieve what your trying to do.

Related

get HttpServletRequest in Spring MVC?

I am using Spring MVC. I am not using Spring boot dependencies.
I created the AuthenticationSuccessEventListener class, this class implements the ApplicationListener interface.
How do I get the HttpServletRequest in the AuthenticationSuccessEventListener class? I tried many options, but I still could not find the answer to my question.
When trying to get the HttpServletRequest, I get an exception.
Message: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Who can, tell me please, what am I doing wrong?
#Component
public class AuthenticationFailureListener implements ApplicationListener<AuthenticationSuccessEvent> {
// This option doesn't work.
// #Autowired
// HttpServletRequest httpServletRequest;
// This option doesn't work.
// HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
#Override
public void onApplicationEvent(AuthenticationSuccessEvent a) {
}
}

OPTIONS request handler should be called before API handler

I have a working #RestController component that yields API web endpoints.
This is one of those endpoints
#CrossOrigin
#GetMapping(API_VERSION + PLAYER + METHOD_FETCH + "/{uid:^[0-9]*$}")
public Player fetchPlayer(#PathVariable("uid") String uid) {
return mongoTemplate.findById(uid, Player.class);
}
Now when using my Vue.js App I call this endpoint. The problem is the axios http client library turns a get request that has authentication headers into a options request to probe the server for actual access.
Now I need to consume this options request and have it be enabled for CORS. I did the following therefore:
#RestController
#Log
#RequestMapping("/**")
public class AuthenticationEndpoint {
#CrossOrigin
#RequestMapping(method = RequestMethod.OPTIONS)
public void handleOptionRequest(){
log.info("option request handled");
}
}
I map it to every url so it "should" intercept every OPTIONS request. But it does not. When having a
GET http://{{host}}:80/api/v0.1/player/fetch/4607255831
Authorization: Basic MTIzNTM2NDMyNDphYmMxMjM=
The more specific API web endpoint is handled before the OPTIONS handler.
How can I actually put the OPTIONS handler before the others in Spring MVC?
I want it to act like an interceptor
OR
What is the best practise way to achieve the wanted behaviour? I kinda feel I am hacking around a better solution.
How can I actually put the OPTIONS handler before the others in Spring MVC? I want it to act like an interceptor.
Your can create a component a class that implements Filter interface and give it a High order :
#Component
#Order(1)
public class RequestInterceptor implements Filter {
#Override
public void doFilter
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String httpMethod = req.getMethod();
if(HttpMethod.OPTIONS.name().equals(httpMethod)){
//do something here before reaching the method handler
}
chain.doFilter(request, response);
}
// other methods
}
Or you can extends OncePerRequestFilter.java and make the same check as above in the doFilterInternal method.
EDIT
If you want to control whether to proceed handling a giving request or not you can use HandlerInterceptor :
A HandlerInterceptor gets called before the appropriate HandlerAdapter
triggers the execution of the handler itself. This mechanism can be
used for a large field of preprocessing aspects, e.g. for
authorization checks, or common handler behavior like locale or theme
changes. Its main purpose is to allow for factoring out repetitive
handler code.
HandlerInterceptor is basically similar to a Servlet
Filter, but in contrast to the latter it just allows custom
pre-processing with the option of prohibiting the execution of the
handler itself, and custom post-processing. Filters are more powerful,
for example they allow for exchanging the request and response objects
that are handed down the chain. Note that a filter gets configured in
web.xml, a HandlerInterceptor in the application context.
#Comonent
public class LoggerInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler)
throws Exception{
// do checks and decide wether to complete or to stop here
// true if the execution chain should proceed with the next interceptor or the handler itself.
// Else, DispatcherServlet assumes that this interceptor has already dealt with the response itself.
return true;
}
// other methods
}

How can I lookup the method being called on a Handler from a Spring HandlerInterceptor?

I have a Spring HandlerInterceptor intercepting the frontend URL's in my application (/app/*). I want to determine which action method in the Handler is about to be invoked from within the HandlerInterceptor. Is there a way to look that up, do I need to inject something into the interceptor that can look that up based on the requested path?
The Interceptor is like this:
public class PageCacheInterceptor implements HandlerInterceptor {...}
It is mapped like this:
<mvc:interceptors>
<bean class="com.example.web.interceptors.PageCacheInterceptor" />
</mvc:interceptors>
Background (because I know you'll ask!). I am adding simple page caching to my app and want to use an annotation like #Cacheable on each suitable method in the controller. The interceptor can then determine whether to cache a response based on the action that created it.
For example:
#RequestMapping(value = "", method = RequestMethod.GET)
#Cacheable(events={Events.NEW_ORDER,Events.NEW_STAT})
public String home(Model model) {...}
The events are the ones that cause the cache to be invalidated. For example /widget/list action would have it's cached response invalidated by a new widget being saved.
Edit: I've upgraded to the latest Spring 3.1 M2, as this blog post hinted at features I need, but it's not clear whether injecting these new classes or sub-classing them will be required. Has any one used them to retrieve the HandlerMethod in an interceptor?
Ok so the solution was actually really easy:
1) Upgrade to Spring 3.1
2) RTFM (properly)
For example a HandlerInterceptor can cast the handler from Object to HandlerMethod and get access to the target controller method, its annotations, etc
3) Cast the handler object to HandlerMethod in the Interceptor.
Then you can do this sort of thing:
HandlerMethod method = (HandlerMethod) handler;
Cacheable methodAnnotation = method.getMethodAnnotation(Cacheable.class);
if (methodAnnotation != null) {
System.out.println("cacheable request");
}
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Pre-handle");
HandlerMethod hm=(HandlerMethod)handler;
Method method=hm.getMethod(); if(method.getDeclaringClass().isAnnotationPresent(Controller.class)){
if(method.isAnnotationPresent(ApplicationAudit.class))
{
System.out.println(method.getAnnotation(ApplicationAudit.class).value());
request.setAttribute("STARTTIME",System.currentTimemillis());
}
}
return true;
}
This post has more details,hope this helps http://www.myjavarecipes.com/spring-profilingaudit-using-mvc-filters/

Obtaining actual parameter values in a Jersey ResourceFilterFactory

I want to implement custom authorisation in my REST services using Jersey. This custom authorisation inspects annotations on methods as well as the actual parameters that a
method receives.
My jax-rs annotated method looks like:
#GET
#Path("customers")
#Requires(Role.CustomerManager)
public Customer getCustomer(#ParseFromQueryString #CheckPermission final Customer customer) {
// ...
}
The #ParseFromQueryString is an annotation that indicates Jersey (through an Injectable provider) to unmarshall a Customer from a query string. The code for that looks like:
public class QueryStringCustomerInjectable implements Injectable<Customer> {
public Customer getValue() {
final Customer customer = new Customer();
// ... a UriInfo was injected using the #Context annotation
// ... extract parameters from QueryString and use setters
return customer;
}
}
The #CheckPermission annotation indicates my custom authoriser that permissions are to be checked on a customer. Some users have access to information on some customers. Similarly, the #Requires annotation takes a role that the invoker should have. These are not java's security roles (Strings), rather, they are enum values.
Using Jersey's ResourceDebuggingFilter as a starting point, I have been able to get to the point of knowing which method will be invoked. However, I still haven't figured out how to determine which parameters will actually be used to invoke the method.
At the top of my head, I can think of two work arounds:
A Method interceptor using Guice + Jersey.
Code this logic in the QueryStringCustomerInjectable, but this seems a bit sloppy. It would be a class doing too much.
Yet, I would really like to do this using only Jersey / JAX-RS. I feel that I am so close!
Ideas? Pointers?
Thanks!
You should use Filters or Interceptors to handle all the information about method.
see Jersey Filter and Interceptors
For the Customer deserialization you could implement the javax.ws.rs.ext.ParamConverterProvider and register it into Jersey. Then you can inject it into your methods with #QueryParam("customer"). It's a bit more flexible since you can use it also with #BeanParam or #PathParam annotations.
Then you can use the ContainerRequestFilter. See as a reference how jersey does the Oauth1 for example OAuth1ServerFilter.
The next thing you can do is to create maybe a feature which will register the newly created filter (see Oauth1ServerFeature for a reference - I couldn't find the source code right now).
Good luck!
Why not using your own Servlet filter e.g.
public class YourFilter implements Filter {
...
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
// HttpServletRequest httpReq = (HttpServletRequest) request;
// HttpServletResponse httpResp = (HttpServletResponse) response;
// HttpServletRequest httpReq = (HttpServletRequest) request;
// HttpServletResponse httpResp = (HttpServletResponse) response;
// ..... httpReq.getUserPrincipal();
// then set what you need using ThreadLocal and use it inside your resource class
// do not forget to call
filterChain.doFilter(request, response); // at the end of this method
}
The last step is to register your servlet filter. This is done using web app's web.xml
It will intercept your HTTP requests before the actual code inside jersey resource is called.

Resteasy security interceptor - how to obtain client IP address inside interceptor?

I have implemented an interceptor to carry out a security check on the client IP address with the following annotations -
#Provider
#ServerInterceptor
#Precedence("SECURITY")
The preprocess method takes the parameters HttpRequest request, ResourceMethod method.
Is there a way of obtaining the client's IP address from the Resteasy HttpRequest object?
I can implement a filter to get around this, but would like to keep security checks in the one place.
The client IP address is available from the request object. But you can't use that for security purposes as it isn't unique per client: it might just be the address of the nearest proxy, even your own.
This (my) answer is wrong!
The HttpServletRequest is "injected" only when the filter class is instantiated, so the instance "see" the same HttpServletRequest for all the subsequent requests (the HttpServletREquest is always the first!!!!!)
You can inject the HttpServletRequest object to access the client ip (I'm using it)
#Provider
#Interceptor
#Precedence("SECURITY")
public class JAXRSInterceptor implements PreProcessInterceptor
{
**#Context HttpServletRequest request; // WRONG WRONG WRONG**
#Override
public ServerResponse preProcess(HttpRequest arg0, ResourceMethod arg1) throws Failure, WebApplicationException
{
System.out.println(request.getRemoteAddr());
System.out.println(request.getRemoteHost());
}

Categories

Resources