Get Parameter Encoding - spring

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;
}
}

Related

Jersey #HeaderParam annotation in resource method paramenter not working with servlet filter

In the method in my resource class, I am accepting a request header value
#GET
#Path(value = "/identifiers")
#Produces(MediaType.APPLICATION_JSON)
public Response getXXX (#HeaderParam("Authorization") String authHeader){...}
I also have a servlet filter defined in web.xml for all incoming requests.
The way my application flow works is -
User requests my rest API and sends an Authorization header in request. My servlet filter will intercept the request and validate the Authorization header and for some users, it replaces this Authorization header with a new value.
The request then goes to the resource class and it uses this authorization header and does some action.
For the users whose Authorization header is changed by the filter, I noticed that the authHeader variable still has the original value.
E.g. - User makes a request containing Authorization header with a value "QwErTyUiOp". The servlet filter injects a new Authorization header in the request with a value "aSdFgHjKl". However, authHeader parameter still has "QwErTyUiOp".
When I iterated through the request object in my method, I could see that the request has the new Authorization header values ("aSdFgHjKl") so the filter is doing its job.
Can someone help me understand why is #HeaderParam capturing the header value before servlet filter has processed the request and if there is any way to alter this behavior?
Here is the web.xml from my application -
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>library-api</display-name>
<filter>
<filter-name>libUserFilter</filter-name>
<filter-class>org.rajiv.library.logic.filter.LibraryUserAuthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>libUserFilter</filter-name>
<url-pattern>/v1/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>Library API App</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>org.rajiv.library.resources</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>AdminServlet</servlet-name>
<servlet-class>org.rajiv.library.admin.AdminServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Library API App</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AdminServlet</servlet-name>
<url-pattern>/restricted/*</url-pattern>
</servlet-mapping>
</web-app>
and the filter class is -
public class LibraryUserAuthFilter implements Filter{
#Override
public void destroy() {
LOG.info("{} Destroyed", getClass());
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
IdsRequest idsRequest = IdsRequest.from(httpRequest);
try (LoggingContext context = LoggingContext.create()) {
TokenResolver.INSTANCE
.extractTokenFromHeaderOrCookie(idsRequest)
.map(TokenDigester.INSTANCE::computeTokenDigest)
.ifPresent(digestedToken -> context.put(CustomLoggingContext.SESSION.toString(), digestedToken));
Optional<HttpServletRequest> modifiedRequest = Optional.empty();
try (LoggingContext libAuthContext = LoggingContext.create()) {
libAuthContext.put(CustomLoggingContext.COMPONENT.toString(), SdkComponents.SDK_LIB_AUTH.toString());
LOG.info("Validation started for request to path:{}", httpRequest.getRequestURI().toString());
modifiedRequest = Optional.of(validate(idsRequest));
} catch (IdentityServicesSdkException ex) {
context.put(CustomLoggingContext.INCIDENT_ID.toString(), ex.getIncidentId());
ProblemResponseWriter.INSTANCE.writeStatusAndProblem(idsRequest, httpResponse, ex);
LOG.warn("Validation failed: {}", ex.getErrorCode());
}
if(modifiedRequest.isPresent()) {
chain.doFilter(modifiedRequest.get(), servletResponse);
}
}
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
initializeScheme(filterConfig);
initializeHost(filterConfig);
initializePort(filterConfig);
String serviceName = filterConfig.getServletContext().getContextPath().replaceAll("/", "").trim();
if(serviceName.isEmpty()) {
serviceName = Optional
.ofNullable(System.getenv("SERVICE_NAME"))
.orElseGet(() -> "service-name-unavailable");
}
LOG.info("{} Initialized", getClass());
}
private void initializeScheme(FilterConfig filterConfig) {
String initParam = filterConfig.getInitParameter(PROXY_SCHEME_ENVIRONMENT_VARIABLE);
if(Strings.isNullOrEmpty(initParam)) {
initParam = loadAuthNSchemeFromEnvVar();
}
scheme = initParam;
LOG.info("HOST_SCHEME: {}", scheme);
}
private void initializeHost(FilterConfig filterConfig) {
String initParam = filterConfig.getInitParameter(PROXY_HOST_ENVIRONMENT_VARIABLE);
if(Strings.isNullOrEmpty(initParam)) {
initParam = loadAuthNHostFromEnvVar();
}
host = initParam;
LOG.info("HOST: {}", host);
}
private void initializePort(FilterConfig filterConfig) {
String initParam = filterConfig.getInitParameter(PROXY_PORT_ENVIRONMENT_VARIABLE);
Integer parsedInitParam = null;
if(!Strings.isNullOrEmpty(initParam)) {
parsedInitParam = Integer.valueOf(initParam);
}
if(parsedInitParam == null) {
parsedInitParam = loadAuthNPortFromEnvVar();
}
port = parsedInitParam;
LOG.info("HOST_PORT: {}", port);
}
}

Custom spring filter not getting called when web application is accessed or url is hit

Below is my configuration in web.xml and I have one JwtFilter but it is not getting access when rest urls are been called.
web.xml
<web-app
<display-name>Portal Web</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet-spring-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>jwtFilter</filter-name>
<filter-class>com.pingle.lola.authentication.JwtFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>jwtFilter</filter-name>
<url-pattern>/portal/lola/*</url-pattern>
</filter-mapping>
This is my JwtFilter
public class JwtFilter extends GenericFilterBean {
#Override
public void doFilter(final ServletRequest req,
final ServletResponse res,
final FilterChain chain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) req;
System.out.println("came here");
final String authHeader = request.getHeader("Authorization");
System.out.println("came here - " + authHeader);
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
System.out.println("should throw");
throw new ServletException("Missing or invalid Authorization header.");
}
final String token = authHeader.substring(7); // The part after "Bearer "
System.out.println("came here" + token);
try {
final Claims claims = Jwts.parser().setSigningKey("secretkey")
.parseClaimsJws(token).getBody();
request.setAttribute("claims", claims);
}
catch (final SignatureException e) {
throw new ServletException("Invalid token.");
}
chain.doFilter(req, res);
}
}
and I have controller where basic rest API are confugured. I am trying to check if any URL is hit like localhost:8080/portal/lola/getData .. it should go to JwtFilter and check for authentication token in header of request and if valid pass it on the controller other wise throw error message. Logic is written properly but filter is not called and when I hit above URL, it goes to controller directly without reaching filter.
my spring config.xml
<context:component-scan base-package="com.pingle.lola.controller"/>
<mvc:annotation-driven/>
//Dont know why I created it when its not mapped to any controller :(
<mvc:default-servlet-handler/>
It seems like /portal is name of application context. Filter url-pattern should not contain name of context. This means, that filter url-pattern should be /lola/* without /portal. Try to change filter mapping to:
<filter-mapping>
<filter-name>jwtFilter</filter-name>
<url-pattern>/lola/*</url-pattern>
</filter-mapping>

SpringMVC Session Timeout - Redirect to a Special JSP

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
}
}

Custom filters in Spring

I coded my own Spring filter in order to encode in UTF-8 all the responses except for images:
package my.local.package.filter;
public class CharacterEncodingFilter extends org.springframework.web.filter.CharacterEncodingFilter
{
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException
{
if(!request.getRequestURI().endsWith("jpg") &&
!request.getRequestURI().endsWith("png") &&
!request.getRequestURI().endsWith("gif") &&
!request.getRequestURI().endsWith("ico"))
{
super.doFilterInternal(request, response, filterChain);
}
filterChain.doFilter(request, response);
}
}
I'm referencing it in the web.xml:
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>my.local.package.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Everything works as expected, jpg/png/gif/ico files are not encoded in UTF-8 while all the other files are.
I'm now trying to code a simple controller which has to return a 404 error under certain conditions:
#Controller
public class Avatar
{
#RequestMapping("/images/{width}x{height}/{subject}.jpg")
public void avatar(HttpServletResponse response,
#PathVariable("width") String width,
#PathVariable("height") String height,
#PathVariable("subject") String subject) throws IOException
{
...
// if(error)
// {
response.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found");
return;
// }
...
}
}
But when requesting, for example, /images/52x52/1.jpg i get a page containing this error:
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
I think I coded the filter in a wrong way (I'm not experienced with Spring), because if I specify org.springframework.web.filter.CharacterEncodingFilter instead of my.local.package.filter.CharacterEncodingFilter in the web.xml file, it works perfectly.
Can someone help me?
Thank you.
You are calling filterChain.doFilter(request, response); twice. Once in your code and once in super.doFilterInternal(request, response, filterChain);
To fix this, simply put your doFilter in the else clause to your if.

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>

Resources