SpringMVC Session Timeout - Redirect to a Special JSP - spring

I've looked everywhere but haven't found a simple solution.
We have a special JSP, timeout.jsp, that needs to be shown whenever a SpringMVC module intercepts an invalid session action. The timeout is already configured in web.xml and works correctly.
Previously in Struts, it was a matter of defining a forward and intercepting dispatchMethod,
<forward name="sessionTimeout" path="/WEB-INF/timeout.jsp" redirect="false" />
#Override
protected ActionForward dispatchMethod(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response, final String name)
throws Exception {
//...
if (!isSessionValid())
return mapping.findForward("sessionTimeout");
}
But how would you implement a catch-all solution in SpringMVC modules?
All my SpringMVC URLs come to this servlet mapping, *.mvc:
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>*.mvc</url-pattern>
</servlet-mapping>
Anything that sends a URL with this pattern should be cross-checked for session validity and if invalid, redirected to timeout.jsp.
NOTE
The solution given here (https://stackoverflow.com/a/5642344/1005607) did not work:
<web-app>
<error-page>
<exception-type>org.springframework.web.HttpSessionRequiredException</exception-type>
<location>/index.jsp</location>
</error-page>
</web-app>
There's a NullPointerException in my SpringMVC Form Code even before any kind of SessionRequiredException, as soon as I try to access the session. I need to globally protect against these NullPointerExceptions.

My final solution: an old-fashioned Filter. It works for me, no other simple solution available.
web.xml
<filter>
<filter-name>spring_mvc_controller_filter</filter-name>
<filter-class>myapp.mypackage.SpringMVCControllerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>spring_mvc_controller_filter</filter-name>
<url-pattern>*.mvc</url-pattern>
</filter-mapping>
SpringMVCControllerFilter
public class SpringMVCControllerFilter implements Filter
{
#Override
public void destroy() {
// TODO Auto-generated method stub
}
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpSession session = request.getSession(false);
if (session.isValid() && !session.isNew())
{
chain.doFilter(request, response);
}
else
{
request.getRequestDispatcher("/WEB-INF/jsp/sessionTimeout.jsp").forward(request, response);
}
}
#Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}

Related

PostConstruct method will not be called after login

In our application we have a dashboard, which will be loaded after login from an init() method with PostConstruct annotation.
Everything works fine, until the session is expired. In this moment, if I click on a button in dashboard, this init method will be called again, although I am not logged in. I will be redirected to the login page and now if I login, the PostConstruct method will not be called anymore and the content of dashboard can not be loaded.
I know that the PostConstruct will be called only once after a session is created (The Controller class is #SessionScoped). I guess the problem is that the server creates a new session after timeout, because the init method get called after timeout and before login, and that leads to not being called after login again. What would be the best solution to solve this problem?
One workaround would be to load the content of dashboard in a method which is not annotated with PostConstruct. But I wonder if the problem can be solved differently.
You might implement a Servlet filter to monitor the status of your user sessions. This way, you will detect the expired session out of the Managed Bean and the init method won't be called.
This filter might look like:
public class UriFilter implements javax.servlet.Filter {
#Inject SessionController session;
private static final String SIGNON_PAGE_URI = "/myappname/engine/index.xhtml";
private static final String SUBDOMAIN_URI = "/myappname/engine/";
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse)response;
HttpServletRequest req = (HttpServletRequest )request;
String uri = ((HttpServletRequest) request).getRequestURI();
if( !this.authorize(req ) && !(uri.endsWith("/") || uri.endsWith("index.xhtml") || !uri.endsWith(".xhtml")) ){
if(request.getParameter("fileName") != null)
res.sendRedirect(SIGNON_PAGE_URI+"?uri="+uri.substring(SUBDOMAIN_URI.length(), uri.length())+"?fileName="+request.getParameter("fileName"));
else {
res.setHeader("Cache-Control","no-cache, no-store, must-revalidate");
res.setHeader("Pragma","no-cache");
res.setDateHeader("Expires",0);
res.sendRedirect(SIGNON_PAGE_URI+"?faces-redirect=true");
}
} else{
//Desativa o cache do browser
res.setHeader("Cache-Control","no-cache, no-store, must-revalidate");
res.setHeader("Pragma","no-cache");
res.setDateHeader("Expires",0);
//Processa request e response
chain.doFilter( req, res );
}
}
private boolean authorize( HttpServletRequest req ){
boolean authorized = false;
HttpSession session = req.getSession(false);
if(session != null){
if(this.session != null) {
if(this.session.getLogged() != null) {
authorized = true;
}
}
}
return authorized;
}
#Override
public void destroy() {
}
}
The SessionController is the #SessionScoped that track the logged user.
In your web.xml file you have to specify the filter:
<filter>
<filter-name>URI Filter</filter-name>
<filter-class>com.myappname.filter.UriFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>URI Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/engine/*</url-pattern>
</filter-mapping>

understanding spring filters in Spring 3.2.8

I am implementing a filter for security reasons.... The point that the page gets frozen and I don't know exactly why because the filter in fact is not still doing anything !
<!-- spring security csrf -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>fr.telecom.support.context.DevicesSecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Here my filter:
public class DevicesSecurityFilter extends DelegatingFilterProxy {
public DevicesSecurityFilter() {
// TODO Auto-generated constructor stub
}
public DevicesSecurityFilter(Filter delegate) {
super(delegate);
}
public DevicesSecurityFilter(String targetBeanName) {
super(targetBeanName);
}
public DevicesSecurityFilter(String targetBeanName,
WebApplicationContext wac) {
super(targetBeanName, wac);
}
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
System.out.println ("do Filter...");
//super.doFilter(request, response, filterChain);
}
}
The filter is doing something: it prevents the request from going to the next filter/servlet in the chain, and doesn't send anything to the response. So it basically intercepts all requests and responds with a blank response to all of them.
For the filter to be "transparent", its doFilter() method must contain
filterChain.doFilter(request, response);
or, since it's a DelegatingFilterProxy, it shouldn't have any doFilter() method at all, and instead let the parent's doFilter method implementation do its job: delegating to the Spring bean it's configured to use. In fact, you shouldn't even create subclasses of DelegatingFilterProxy: as its name indicates, it works, on its own, by delegating to a Spring bean. The Spring bean should be the one doing the filtering job.
By overriding the doFilter() method, you're preventing that delegation to happen.

Aspect to wrap around log entries

I am using the sl4j Logger throughout my spring application.
I would like to append a custom string to all log entries (info/trace/debug etc) done throughout the application. This would ideally be done using an Aspect however I am not sure what format the aspect would have. I am assuming something along the lines of
#Around("org.slf4j.Logger.info(*)")
however i cannot find any reliable way to make this apply to all the methods involved correctly.
As #PavelHoral mentioned The following was the solution using MDC
Create your own filter
import org.slf4j.MDC;
import javax.servlet.*;
import java.io.IOException;
public class MDCLoggingFilter implements Filter {
#Override
public void init(final FilterConfig filterConfig) throws ServletException {}
#Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
MDC.put("myKey", "myValue");
try {
chain.doFilter(request, response);
} finally {
// remove the key once you are done with it
MDC.remove("myKey");
}
}
#Override
public void destroy() {}
}
Then add your filter to your web.xml as follows
<filter>
<filter-name>mdcLoggingFilter</filter-name>
<filter-class>path.to.MDCLoggingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>mdcLoggingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
However, this does not seem to be applying to all my messages. some warnings seem to not be displaying the field. currently investigating.

How ask a browser to not store cache Java EE/Tomcat

I want to my browser not to store cache, when I update the content of my server I always have the first version of a document.
But when erase cache on my browser everything's ok.
Is there anyway to tell the browser not to store cache when running my webApp ?
I am using Java EE (JSPs) and Apache Tomcat Server.
You can use a ServletFilter to ensure that the HTTP response contains headers to instruct browsers not to cache:
public class NoCachingFilter implements Filter {
public void init(FilterConfig filterConfig) {
}
public void destroy() {
}
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("Cache-Control", "no-cache");
httpResponse.setDateHeader("Expires", 0);
httpResponse.setHeader("Pragma", "no-cache");
httpResponse.setDateHeader("Max-Age", 0);
chain.doFilter(request, response);
}
}
and then configure the web.xml to use that filter for all requests:
<filter>
<filter-name>NoCachingFilter</filter-name>
<filter-class>my.pkg.NoCachingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>NoCachingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Get Parameter Encoding

I have a problem using spring mvc and special chars in a GET request. Consider the following method:
#RequestMapping("/update")
public Object testMethod(#RequestParam String name) throws IOException {
}
to which I send a GET request with name containing an "ä" (german umlaut), for instance. It results in spring receiving "ä" because the browser maps "ä" to %C3%A4.
So, how can I get the correct encoded string my controller?
Thanks for your help!
You're having this problem, because the request differentiates between body encoding and URI encoding. A CharacterEncodingFilter sets the body encoding, but not the URI encoding.
You need to set URIEncoding="UTF-8" as an attribute in all your connectors in your Tomcat server.xml. See here: http://tomcat.apache.org/tomcat-6.0-doc/config/ajp.html
Or, alternatively, you can set useBodyEncodingForURI="True".
If you're using the maven tomcat plugin, just add this parameter:
mvn -Dmaven.tomcat.uriEncoding=UTF-8 tomcat:run
What about this? Could it help?
In your web.xml:
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.example.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<servlet-name>dispatcher</servlet-name>
</filter-mapping>
com.example.CharacterEncodingFilter:
public class CharacterEncodingFilter implements Filter {
protected String encoding;
public void init(FilterConfig filterConfig) throws ServletException {
encoding = filterConfig.getInitParameter("encoding");
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
request.setCharacterEncoding(encoding);
filterChain.doFilter(servletRequest, servletResponse);
}
public void destroy() {
encoding = null;
}
}

Resources