8

I am using Jersey in my Web-application. The data sent to the server is in JSON format, which in turn is unmarshalled at the server-end and the object obtained is used in further processing. The security audit raised some vulnerabilities for this approach.

My Rest Code:

@POST
@Path("/registerManga")
@Produces(MediaType.APPLICATION_JSON)
public Response registerManga(MangaBean mBean){
    System.out.println(mBean);
    return Response.status(200).build();
}

MangaBean:

public class MangaBean {
    public String title;
    public String author;

    @Override
    public String toString() {
        return "MangaBean [title=" + title + ", author=" + author + "]";
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }


}

The data is sent in this format:

["title":"Bleach","author":"kubo tite"]

The above data is successfully unmarshalled into an object and I get this as the output:

MangaBean [title=Bleach, author=kubo tite]

But if the data is changed to:

["title":"<script>alert("123");</script>","author":"kubo tite"]

A 500 internal server error occurs and is displayed to the user:

javax.servlet.ServletException: org.codehaus.jackson.JsonParseException: Unexpected character ('1' (code 49)): was expecting comma to separate OBJECT entries
 at [Source: org.apache.catalina.connector.CoyoteInputStream@19bd1ca; line: 1, column: 28]
    com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:420)
    com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537)
    com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:699)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

The unexpected occurrence of "" is causing errors in the parser. As the unmarshalling is done behind the scenes and I have no control over it, I am unable to handle the exception being raised.

My question is how can I handle this exception and return a proper response to the user instead of a stacktrace. Please advice.

6 Answers 6

17

Register an exception mapper to handle the JSON parsing exceptions:

@Provider
class JSONParseExceptionMapper implements ExceptionMapper< JsonParseException > {
    @Override
    public Response toResponse(final JsonParseException jpe) {
        // Create and return an appropriate response here
        return Response.status(Status.BAD_REQUEST)
                .entity("Invalid data supplied for request").build();
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

I don't really understand how to use the @Provider syntax.. Can I use this to handle the following scenario: Unruly API returns [] when a Map is empty rather than {}. Seems like from the above, I could map this exception and handle it ?
I cannot for the life of me get this to work in Jersey 2.13. Ugh.
I think the missing part here is that you still need to define to the jaxb beforeUnmarshal(Unmarshaller u, Object parent) callback event and register a listener that just rethrows the exception.
had to make the class public with wildfly 8.x, otherwise it complained about missing constructor
@BobKuhar See also question #34615242 and try to register mapper and also apply @Priority.
2

If this exception mapper isn't being called (as John Ding's comment indicated), make sure you have it registered with your ResourceConfig.

Also, take note that when using the JacksonFeature (with Jersey 2.x) it includes an exception mapper for this, but if you register your own it will take precedence.

Here is an example of registering it by package. So put JSONParseExceptionMapper in "your.package.here" and it will get picked up.

@ApplicationPath("whatever")
public class MyAppResourceConfig extends ResourceConfig
{
    public MyAppResourceConfig()
    {
        packages("your.package.here");
        register(JacksonFeature.class);
    }
}

For the original question, you'll need to handle JsonMappingExceptionMapper as well.

Comments

1

In addition to @Perception's answer, the missing part is that the exceptions get swallowed and not reported. You should pass a validation listener:

private static final String[] severity = new String[] {"Warning", "Error", "Fatal Error"};
void beforeUnmarshal(Unmarshaller u, Object parent) throws JAXBException {
    u.setEventHandler((evt) -> {
        throw new WebApplicationException(severity[evt.getSeverity()]+": Error while parsing request body: " + evt.getMessage(), evt.getLinkedException(), 400);
    });
}

Just drop this code in your JAXB bean and your all set.

Comments

0

Adding full class example of Perception answer

package com.shashi.service;

import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

import org.apache.log4j.Logger;

import org.codehaus.jackson.JsonParseException;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.talklingo.service.v1.UserManagementService;
@Provider
public class JSONParseExceptionMapper implements ExceptionMapper< JsonParseException > {

 private static Logger logger = Logger
   .getLogger(JSONParseExceptionMapper.class);

   public Response toResponse(final JsonParseException jpe) {
         // Create and return an appropriate response here

         return Response.status(Status.BAD_REQUEST)
                 .entity("Invalid data supplied for request").build();

     }
}

1 Comment

This does not get called, what else do I need to do?
0

The other option could be in the ResourceConfig, register the JsonParseExceptionMapper class.

register(JsonParseExceptionMapper.class);

Comments

0

Add the exception handling class in same package(or sub package) mentioned in the web.xml file

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.