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) {
}
}
Related
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.
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
}
Building Spring Boot application, deploying(by copying to webapps folder while Tomcat is down) to local Tomcat8. Always get an error:
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/DispatcherPortlet:
In this case, use RequestContextListener or RequestContextFilter to expose the current request.
As I understand, problems are while instantiating bean with WebAuthenticationDetails extending:
#Component
public class AuthDetails extends WebAuthenticationDetails{
private final AuthTarget authTarget;
public AuthDetails(HttpServletRequest request) {
super(request);
this.authTarget = AuthTarget.valueOf(request.getParameter("target"));
}
public AuthTarget getAuthTarget(){
return this.authTarget;
}
}
It cannot provide HttpServletRequest for bean constructing, but I don't know how to evade it.
Tried to add RequestContextListener, in xml or as implementation(and marking as #WebListener), no effect.
Out of ideas, how to fix it. Tried example from here: https://github.com/Baeldung/spring-security-registration , no changes - same error at the similar place.
Any help is greatly welcome.
The key was simple: I should define filter bean explicitly in security configuration extends WebSecurityConfigurerAdapter:
#Bean
AuthFilter authFilter() throws Exception{
AuthFilter authFilter = new AuthFilter();
return authFilter;
}
instead of autowiring it.
I'm implementing routing datasources in my Spring application. One of method to get lookup key is accessing HttpServletRequest and getting current domain as key by invoking method
request.getServerName()
HttpServletRequest is accessing via RequestContextHolder as below
(ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()
or just by autowiring HttpServletRequest
#Autowired
private HttpServletRequest request;
Everything is working correctly when I'm in request scope, using standard #RequestMapping annotation in controller.
I want to do same thing in WebSocket method annotated by #MessageMapping. There is no request scope so Autowiring HttpServletRequest and invoking methot getServerName() gives exception as below
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/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Message is passed to controller using Stomp and SockJs. Here is my configuration
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/sub");
config.setApplicationDestinationPrefixes("/some");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").withSockJS();
}
And Controller
#Autowired
private SomeService service;
#MessageMapping("/someUrl/{param}")
public void subscribeForMessage(#DestinationVariable Long param) {
service.doSmth();
}
I do not want to pass it from controller to service because invocation chain is much longer and getting current lookup key have to be transparent.
It is possible to get server name in a way similiar to Autowiring HttpServletRequest? It is possible to inject some "scope" of websocket request or session without passing it ?
You have to initialize bean of RequestContextListener to request object other than #Controller ( Request scope).
#Bean
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
#Controller
public class CentralizedExceptionController extends DefaultHandlerExceptionResolver {
#Override
protected ModelAndView handleNoSuchRequestHandlingMethod(NoSuchRequestHandlingMethodException ex, HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("working?!");
return new ModelAndView();
}
I have this in my code, but in case of a 404 its never called.
(I dont have an error-page defined in my web.xml, and i dont want to)
Take a look at this jira issue: https://jira.springsource.org/browse/SPR-8837?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=72648#comment-72648
If your Spring dispatcher servlet is configured to process all/most URLs, then you are probably getting the 404 error along with this DispatcherServlet log message from console:
No mapping found for HTTP request with URI [xxx]
This indicates that Spring's DispatcherServlet is processing the request but do not have an appropriate #RequestMapping to dispatch to.
A simple solution would be to limit requests processed by dispatcher servlet by reconfiguring web.xml's servlet-mapping > url-pattern to only URLs specified by your application's #RequestMappings. However, this is NOT very practical (so don't do this).
One way to overcome this would be to create a #RequestMapping that handles all "unhandled" request mappings - some kind of fallback request mapping.
#RequestMapping("**")
#ResponseBody
public String fallbackRequestMapping() {
return "do something useful...";
}
Note that this answer is similar in approach to Dani's answer but written with annotation based development in mind. Therefore, it is useful to understand the associated Spring issue.
plz check. Your controller class name should not be Controller.java.
You need to use #ExceptionHandler annotation to your method:
#ExceptionHandler(NoSuchRequestHandlingMethodException.class)
public ModelAndView handleNoSuchRequestHandlingMethod(NoSuchRequestHandlingMethodException ex, HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
...
}