SpringMVC Interceptor cannot handle slashes - java

In the springmvc, when i send this url to spring interceptor, it does not work.
http://localhost/RRAdmin/cgr/cagri.jpg
But when use this url, interceptor works.
http://localhost/RRAdmin/cgr&cagri.jpg
You will see interceptor mapping below
<mvc:interceptor>
<mvc:mapping path="/**.jpg" />
<mvc:mapping path="/**.png" />
<bean class="com.RRAdmin.interceptor.ImageInterceptor" />
</mvc:interceptor>
And you'll see my prehandle method below
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String uri = request.getRequestURI();
File image = new File(uri);
if(image.exists()) sendFile(image, response.getOutputStream());
return false;
}
Thank you.

I think that you have to add a new mapping path like this:
<mvc:mapping path="/**/*.jpg" />
<mvc:mapping path="/**/**.png" />
Hope it helps.

Related

Interceptor is called 2 times more

I use Spring i18n library.
- ReloadableResourceBundleMessageSource
- SessionLocaleResolver
- LocaleChangeInterceptor
There are no errors.
If I use a strong refresh function in chrome, all interceptor methods are executed twice more.
And The Issue only occurs when the pages is used messages.properties.
preHandle ==> Controller ==> postHandle ==> AfterCompletion is executed, and all methods are executed twice more.
I've looked at the lifecycle of the interceptor, but I don't understand why the interceptor runs twice more without reason.
1. servlet-context.xml
<beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="basenames" value="/WEB-INF/messages/messages, /WEB-INF/messages/messages_ko_KR" />
</beans:bean>
<beans:bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<beans:property name="defaultLocale" value="ko_KR" />
</beans:bean>
<interceptors>
<beans:bean id="localeChangeInterceptor" class="com.test.util.locale.LocaleChangeInterceptor" />
</interceptors>
2. LocaleChangeInterceptor is implemented by me and is implemented as simple as the code below.
public class LocaleChangeInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String language = request.getParameter("language");
System.out.println("1. preHandle(): " + language);
if(language != null) {
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
localeResolver.setLocale(request, response, StringUtils.parseLocaleString(language));
}
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("2. postHandle()");
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("3. afterCompletion()");
}
}
Console
1. preHandle(): null
main.jsp
2. postHandle()
3. afterCompletion()
1. preHandle(): null
2. postHandle()
3. afterCompletion()
1. preHandle(): null
2. postHandle()
3. afterCompletion()
I don't know whether it is a problem or a natural result of Interceptor's lifecycle.
Resolved.
It was resolved by first creating an Interceptor bean,
then by calling the registered bean by reference from the .
It seems to be an issue because I didn't know well about Spring interceptor registration. I need to find out more.
<beans:bean id="localeChangeInterceptor" class="com.test.util.locale.LocaleChangeInterceptor" />
<interceptors>
<interceptor>
<mapping path="/**" />
<exclude-mapping path="/resources/**" />
<beans:ref bean="localeChangeInterceptor" />
</interceptor>
</interceptors>

Logging REST/SOAP services using HandlerInterceptorAdapter

I am trying to implement HandlerInterceptorAdapter to be able to capture the request/response as a pre/post processor. For some reason the call doesn't go through my interceptor. There are multiple examples out but I couldn't find the issue in my case. Right now I want to capture the request before it goes to actual service and log some data.
NOTE: I don't have any view to render.
Interceptor class:
public class ESignLoggingInterceptor extends HandlerInterceptorAdapter {
private static final String CLASS_NAME = ESignLoggingInterceptor.class.getSimpleName();
#SuppressWarnings("unused")
#Override
public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler ) throws Exception {
String url = null;
if( request != null ) {
url = request.getRequestURL().toString();
}
return true;
}
}
spring.xml
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/rest"/>
<bean class="com.mercuryinsurance.esignature.common.logging.ESignLoggingInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/soap"/>
<bean class="com.mercuryinsurance.esignature.common.logging.ESignLoggingInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
I know 2 approaches for solving this problem, that I also faced.
The first is like you are trying. Please check:
Change
<mvc:mapping path="/soap"/> to <mvc:mapping path="/soap/**"/>
<mvc:mapping path="/rest"/> to <mvc:mapping path="/rest/**"/>
Also check if you have al schemas declared. If you actually don't have it declared you should be receiving error.
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd"
The second
Declare your interceptor as below
#Bean
public MappedInterceptor myInterceptor() {
return new MappedInterceptor(null, new MyLoggingInterceptor());
}
EDIT: Add #Component to your class

Interceptor preHandle() not redirecting to login.html

I have a spring application. I introduced a sessionInterceptor to prevent direct access to index.jsp. If the user is not logged in it shouldn't be able to access index.jsp and should be redirected to login.html. The code is hitting the preHandle() method and running all the code but after return false it's not redirecting to login.html. What's wrong? Any gurus out there for help? Thanks in advance.
My preHandle() in SessionInterceptor.java is:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
// if displaying the home page, make sure the user is reloaded.
if (request.getRequestURI().endsWith("login.html")) {
session.removeAttribute("isUserLoggedIn");
}
if (session.getAttribute("isUserLoggedIn") == null && !request.getRequestURI().endsWith("login")) {
response.sendRedirect(request.getContextPath() + "/login.html");
return false;
}
return true;
}
I have tried the following as well but all in vain.
RequestDispatcher dispatcher = request.getServletContext().getRequestDispatcher("/login.html");
dispatcher.forward(request, response);
My dispatcher-servlet.xml settings are:
<bean id="sessionInterceptor" class="com.xxx.xxx.xxx.SessionInterceptor" />
<bean id="annotationMapper" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="sessionInterceptor" />
</list>
</property>
</bean>
<!-- Configures Handler Interceptors -->
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.xxx.xxx.xxx.SessionInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
The web.xml is:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
you can try redirecting to a logical path that will be catched from a controller
Try
response.sendRedirect("/NotLogged");
And then create a function like this:
#RequestMapping(value = {"/NotLogged"}, method = RequestMethod.GET)
public String notLogged() {
return "login.html";
}
I hope it will work for you!
When i use return false, i take "Error: Exceeded maxRedirects. Probably stuck in a redirect loop http://localhost:8080/api/login"
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(true){
response.sendRedirect("/api/login");
return false;
}
return true;
}

Whats wrong with HttpServletResponse#addHeader?

I'm running in my web app filter, which recieves from external source info about user, if he's logged in or not. Heres my filter:
#Override
public void doFilter( ServletRequest request, ServletResponse response,
FilterChain chain ) throws IOException, ServletException
{
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String loginBean = httpRequest.getHeader( CommonVariables.LOGIN_BEAN );
if ( loginBean == null )
{
System.out.println( "FILTER-----------" );
try
{
String login;
String domain;
//Here i'm getting login and domain string
loginBean = domain + "\\" + login;
httpResponse.addHeader( "LoginBean", loginBean );
System.out.println( login + " " + domain );
} catch ( Exception e )
{
e.printStackTrace();
//redirect to login page
httpResponse.sendRedirect( "..." );
return;
}
}
chain.doFilter( request, response );
}
Not I though that those header will be passed into next filters. Therefore I implemented Spring Security PRE_AUTH_FILTER:
Spring security context
<http use-expressions="true" auto-config="false" entry-point-ref="http403EntryPoint">
<!-- Additional http configuration omitted -->
<custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
</http>
<beans:bean id="siteminderFilter" class=
"org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<beans:property name="principalRequestHeader" value="LoginBean"/>
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="preauthAuthProvider"
class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService">
<beans:bean id="userDetailsServiceWrapper"
class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<beans:property name="userDetailsService" ref="userDetailsService"/>
</beans:bean>
</beans:property>
</beans:bean>
<beans:bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
<beans:bean id="userDetailsService" class="com.execon.security.CustomUserDetailsService"/>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="preauthAuthProvider" />
</authentication-manager>
Then I tried to parse loginBean String in my CustoUserDetailsService and receive actuall user object. But It is not fired, and app fails with this:
org.springframework.security.web.authentication.preauth.PreAuthenticatedCredentialsNotFoundException: LoginBean header not found in request.
So that means the header is set wrong? Or not set at all? What might be wrong?
Filter setting LoginBean is first one fired, then goes Spring SEcurity. Standard output works ok as I have:
17:12:15,669 INFO [stdout] (http--127.0.0.1-8080-2) FILTER-----------
17:12:15,669 INFO [stdout] (http--127.0.0.1-8080-2) LOGIN DOMAIN
You are setting something in the response and the Spring's class is looking for the same in the request.
The only way you can modify an incoming HttpServletRequest is to decorate it. You should define a class as follows first:
public class AuthHttpServletRequest extends HttpServletRequestWrapper
{
private String loginBean;
public AuthHttpServletRequest(HttpServletRequest aRequest, String loginBean)
{
super(aRequest);
this.loginBean = loginBean;
}
#Override
public String getHeader(String headerName)
{
if(CommonVariables.LOGIN_BEAN.equals(headerName)) {
return this.loginBean;
}
return super.getHeader(headerName);
}
}
Then, replace the following line in your filter:
httpResponse.addHeader( "LoginBean", loginBean );
with this:
request = new AuthHttpServletequest(httpRequest, loginBean);
Then your chain.doFilter gets the request that can return the loginBean as you intended it to, to the Spring's authentication filter class, down in the filter chain.

How to configure Spring to avoid setting Pragma No-Cache

My system is Spring MVC based and I checked that Spring automatically sets PRAGMA: no-cache. The system is available to the users through SSL. When the users try to download something using the INTERNET EXPLORER 7 or 8 an error like "Internet Explorer cannot download file from server" appears (more details: http://support.microsoft.com/default.aspx?scid=KB;EN-US;q316431&).
I tried to configure the WebContentInterceptor like the code bellow but does not work:
<mvc:interceptors>
<bean id="webContentInterceptor" class="org.springframework.web.servlet.mvc.WebContentInterceptor">
<property name="cacheSeconds" value="2100" />
<property name="useExpiresHeader" value="false" />
<property name="useCacheControlHeader" value="false" />
<property name="useCacheControlNoStore" value="false" />
</bean>
</mvc:interceptors>
What can I do avoid Spring send the Pragma: no-cache and related to Cache Control?
Regards!
You can write your own custom interceptor and set the header values to the response object. Interceptors are nothing but filters so override the filter and use the
prehandle and posthandle to set the request and response headers respectively.
Let me know if you want specific examples doing that.
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<beans:bean id="customInterceptor"
class="org.example.interceptors.CustomInterceptor">
</beans:bean>
</mvc:interceptor>
</mvc:interceptors>
public class CustomInterceptor implements HandlerInterceptor{
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object arg2, ModelAndView modelAndView) throws Exception {
response.setHeader(...);}
}
The simplest approach is probably just to stop the header from being written with a servlet filter. This way no Spring configuration has to be modified and you pick up the correct cache functionality for free.
public class PragmaFilter implements Filter {
private static String PRAGMA_HEADER = "Pragma";
#Override
public void init(FilterConfig filterConfig) throws ServletException { }
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, new NoPragmaHttpServletResponseWrapper(response));
}
#Override
public void destroy() { }
private final class NoPragmaHttpServletResponseWrapper extends HttpServletResponseWrapper {
private NoPragmaHttpServletResponseWrapper(ServletResponse response) {
super((HttpServletResponse) response);
}
#Override
public void addHeader(String name, String value) {
if (PRAGMA_HEADER.equals(name)) {
return;
}
super.addHeader(name, value);
}
#Override
public void setHeader(String name, String value) {
if (PRAGMA_HEADER.equals(name)) {
return;
}
super.setHeader(name, value);
}
}
}
Try to set cache seconds to an negative value.
If this does not help you will need to override:
protected final void preventCaching(HttpServletResponse response)
or
protected final void applyCacheSeconds(HttpServletResponse response, int seconds, boolean mustRevalidate)
Both methods are implements in WebContentGenerator
<mvc:interceptors>
<bean id="webContentInterceptor" class="org.springframework.web.servlet.mvc.WebContentInterceptor">
<property name="cacheSeconds" value="2100" />
<property name="useExpiresHeader" value="false" />
<property name="useCacheControlHeader" value="false" />
<property name="useCacheControlNoStore" value="false" />
<property name="cacheMappings">
<props>
<prop key="/**/**">-1</prop><!-- removes pragma no-cache -->
</props>
</property>
</bean>
</mvc:interceptors>

Categories

Resources