Why Spring interceptor is bypassed for bad URLs? - spring-mvc

My web application runs on Spring (MVC) 4.2.9.RELEASE, Hibernate 5.1.3.Final, and Spring Data 1.8.2.RELEASE.
I have the following interceptor in the Spring context.
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="1"/>
<property name="interceptors">
<list>
...
<ref local="myIntercepter" />
...
</list>
</property>
</bean>
The interceptor "myIntercepter" is able to intercept valid URLs such as
http://localhost/s?mid=cflbv1zipb8d7&lang=en_US
However, for the following invalid URL (has a question mark in the end)
http://localhost/s?mid=cflbv1zipb8d7&lang=en_US?
The interceptor does not get called. I am not sure why this behavior happens. I have to make sure all web traffic to go through the interceptor.

If you want to make sure a piece of code gets executed for every web request coming in, I'd recommend using a Filter instead of a HandlerInterceptor. Spring MVC might be trying to parse the querystring or something to that effect prior to the interceptor being called, or it can't find a handler due to the invalid url.

Related

How to avoid display jssession id in Url using spring 4 java annotation configuration

I found is that jsessionid is injected in the url, how can i avoid displaying jsessionid in url. I am using cookies for to have store login information I have not used any http session. I found below suggestion in xml configuration how would I write using spring java annotation configuration can anyone just let me know
<property name="securityContextRepository" ref="securityContextRepositoryNoJSession"/>
<bean id="securityContextRepositoryNoJSession" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository">
<property name="disableUrlRewriting" value="true"/>
</bean>

how to inject userContext in JSP pages

how do I retrieve the values of a context in a jsp file? this tutorial is perfect for what I need but I need to retrieve the property values in the jsp file.
http://www.mkyong.com/spring/spring-listfactorybean-example/
is there a specific interceptor that I can use?
You're referring to spring context right?
In general, JSPs should be a template of a page only, so the only interaction with the back-end should be accessing the values of the scoped attributes. This means that whichever bean value you need you should instead store in the model.
This being said, there are a few ways you can expose spring beans to view. Depends on which View resolver you're using, the ones that extend UrlBasedViewResolver have the setExposeContextBeansAsAttributes property
Set whether to make all Spring beans in the application context
accessible as request attributes, through lazy checking once an
attribute gets accessed. This will make all such beans accessible in
plain ${...} expressions in a JSP 2.0 page, as well as in JSTL's c:out
value expressions.
Default is "false".
You would configure it like
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
<property name="exposeContextBeansAsAttributes" value="true" />
</bean>
Inject your bean (or source) of userContext into your controller, so you have access to it in a local variable.
So taking the example maybe this is:
#Autowired
private CustomerBean customerBean;
#RequestMapping(value="/foobar/index.jsp")
public String (HttpServletRequest request) {
Object userContext = customerBean.getLists();
request.setAttribute("userContext", userContext);
return "/foobar/index.jsp"; // expecting JstlView viewResolver to map to JSP file
}
In the CONTROLLER simply add data to the HttpServletRequest (which you just add as argument to the method to introduce it).
Then use request.setAttribute("userContext", userContext); then in JSP simply access it using Expression Language like ${userContext}. There are other ways using Spring model paradigm but they effectively do the above.
Ensure you have your JstlView setup to https://dzone.com/articles/exploring-spring-controller
More info about how to use EL in JSPs to retrieve data attached to request:
How to obtain request / session / servletcontext attribute in JSP using EL?

Spring AsyncServlet with ActiveMQ, Camel and Jetty

I'm trying to use Spring AsyncServlet with Camel and ActiveMQ. I'm using the following versions.
<spring.version>3.2.0.M1</spring.version>
<camel.version>2.10.0</camel.version>
<jetty.version>8.1.3.v20120416</jetty.version>
<activemq.version>5.6.0</activemq.version>
I want to push messages to clients that are connected to the server (Jetty).
My Camel routes looks like the following.
from("mina:udp://source_machine:9998").to("activemq:myqueue");
I've the following in my Spring/Camel configuration based on this.
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost:61616" />
</bean>
<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
<property name="maxConnections" value="8" />
<property name="maximumActive" value="500" />
<property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactory" />
<property name="transacted" value="false" />
<property name="concurrentConsumers" value="10" />
</bean>
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig" />
</bean>
Using the above configuration I'm able to input messages into my queue (at least I don't get any errors.) However, I've no idea how to read from this queue.
Is this the correct way of configuring ActiveMQ when using Spring, Camel and Jetty ?
How do I add/register a MessageListener javax.jms.MessageListener so that I can read from my queue.
How can I control the queue size and make the queue non-persistent?
It it possible to add multiple listeners
Thanks.
Your config looks good for activemq. No idea about jetty. There is no jetty config in the snippet you provided.
In a camel route you can simply use a from activemq endpoint to listen on the queue.
from("activemq:myqueue").to("log:test");
Btw. I typically use the jms ednpoint instead of the ActiveMQ one. This has the advantage that it is easier to switch to another jms provider if you have to at some point.
You can also use the connectionfactory and use you own DefaultMessageListenerContainer in a bean. See the spring configs for how to do this but this has nothing to do with camel then.
You can control the queue size in the activemq config. Using the http://activemq.apache.org/producer-flow-control.html.
You can not make a queue no persistent but you can define the messages you send to be non persistent. http://activemq.apache.org/how-do-i-disable-persistence.html
You can define many listeners and you can even define the number of threads for one listener using the option maxConcurrentConsumers on the from endpoint above.

How to configure Shiro + Spring MVC when #Controller REDIRECTS to a login page

I have a typical Spring MVC + GWT architecture with Apache Shiro as a security layer.
Problem:
No matter what protocol is used for a request to the App server, pages should be returned in the protocol specified in the request's "X-Forwarded-Proto" header (so, app server can receive a HTTP request, but if the header says HTTPS, it should respond using HTTPS). Obviously, the configuration specified in the Shiro-Spring tutorial won't work as it has nothing to do with the protocols (login.jsp will be returned using the protocol used in request):
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login.jsp"/>
<property name="filterChainDefinitions">
<value>
/** = authc
</value>
</property>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
</bean>
<bean id="myRealm" class="com.myapp.security.DBRealm">
<property name="credentialsMatcher" ref="sha256Matcher"/>
</bean>
Possible solution:
Use #Controller to REDIRECT to the login view with the specified protocol:
#RequestMapping(value="/login", method=RequestMethod.GET)
public RedirectView doLogin(HttpServletRequest req) throws MalformedURLException {
URL originalURL = new URL(req.getRequestURL().toString());
return new RedirectView(new URL(req.getHeader("X-Forwarded-Proto"), originalURL.getHost(), "/login.jsp").toString());
}
and change the loginUrl in shiro configuration to point to /login, so that #controller catches it:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login"/>
... leave everything else the same
</bean>
But with this configuration, although I get the same login page, the myRealm (com.myapp.security.DBRealm) is not triggered at all (meaning, the credentials are not checked), and login always fails. Seems like the redirected page loses the "hook" to the realm.
Any ideas on what I am doing wrong?
The reason this is failing is because the Shiro authc Filter (a FormAuthenticationFilter) expects the loginUrl to be the one where the login attempt occurs.
That is, when authc filters a request that matches the loginUrl, it will automatically support form-based authentication. Because you are redirecting the end-user to a URL that does not match the loginUrl (i.e. loginUrl=/login, but you redirect them to /login.jsp), the authc filter won't perform a login.
Your best option IMO:
Subclass FormAuthenticationFilter and override the redirectToLogin method to use your X-Forwarded-Proto logic. Then redefine 'authc' to be your custom subclass. For example, using shiro .ini:
[main]
...
authc = com.foo.my.FormAuthenticationFilterSubclass
Also, if you want this behavior in Shiro directly (so Shiro looks for that header when performing a redirect by default) so you can remove your subclass, please open a feature request in Apache Shiro's Jira.

How to enable Spring 3.0 MappingJacksonHttpMessageConverter with #ResponseBody AND pre-Spring-3.0 Controller SimpleUrlHandlerMapping together?

As the title suggests, I'm trying and failing to get the following combination working in Spring 3.0:
pre-Spring-3.0 controllers mapped with SimpleUrlHandlerMapping, and,
a Spring-3.0 #Controller using MappingJacksonHttpMessageConverter and #ResponseBody to return JSON.
All the pieces work - except when put together!
In more detail, I have an existing Spring web-app which includes many pre-Spring-3.0 controllers. These implement Controller and are mapped explicitly with a SimpleUrlHandlerMapping bean. (So one solution is to change them all to #Controller style). The same web-app (DispatcherServlet) also supports several newer controllers annotated with #Controller.
My bean config includes the following, and all is good:
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/path/name.ext">mySpring25Controller</prop>
</props>
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
</bean>
Now I'm adding, to a new controller annotated with #Controller and #RequestMapping, use of MappingJacksonHttpMessageConverter so that with #ResponseBody some of my methods can return JSON via Jackson - to Ajax calls. Again all is good:
<!-- to generate JSON responses using Jackson (without using <mvc:annotation-driven/>) -->
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
</list>
</property>
</bean>
The problem is that now my explicit mappings defined in the SimpleUrlHandlerMapping bean are no longer working:
[http-8081-Processor25] ERROR org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/mayapp].[springapp] - Servlet.service() for servlet springapp threw exception
javax.servlet.ServletException: No adapter for handler [com.mycom.controller.mySpring25Controller ...]: Does your handler implement a supported interface like Controller?
at org.springframework.web.servlet.DispatcherServlet.getHandlerAdapter(DispatcherServlet.java:985)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:773)
These mappings still appear in my log at start-up (SimpleUrlHandlerMapping - Mapped URL path ... etc) - but evidently are now broken somehow.
INFO org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapped URL path [/path/name.ext] onto handler [com.mycom.controller.mySpring25Controller ....]
I started with <mvc:annotation-driven/> which had the same problem. I've tried re-ordering without success, including order properties. And I've also not found an explanation in the Spring docs. It seems there is some interaction in the Spring auto-magic which I haven't got to the bottom of.
Interesting problem anyone? Insight gratefully received!
Post and ye shall find (delayed by 8 hours for lack of reputation)!
As per post No adapter for handler exception the answer appears to be that the explicit AnnotationMethodHandlerAdapter definition blows away the implicit SimpleControllerHandlerAdapter which was previously satisfying the SimpleUrlHandlerMapping mappings.
So add it explicitly:
<bean
class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter">
</bean>
And we're good, though at the same time you might also need to introduce also an explicit replacement for the implicit HttpRequestHandlerAdapter also blown away:
<bean
class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter">
</bean>

Resources