如何在解组JSON数据期间处理解析器异常?

时间:2013-02-13 12:47:39

标签: java json parsing jersey pojo

我在网络应用程序中使用Jersey。发送到服务器的数据是JSON格式,而后者在服务器端解组,获得的对象用于进一步处理。安全审计为这种方法带来了一些漏洞。

我的休息代码:

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


}

数据以这种格式发送:

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

以上数据已成功解组到对象中,我将其作为输出:

MangaBean [title=Bleach, author=kubo tite]

但如果数据更改为:

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

发生500内部服务器错误并显示给用户:

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)

""的意外发生导致解析器出错。由于解组是在幕后完成的,我无法控制它,我无法处理被引发的异常。

我的问题是如何处理此异常并向用户返回正确的响应而不是堆栈跟踪。请指教。

6 个答案:

答案 0 :(得分:16)

注册一个异常映射器来处理JSON解析异常:

@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();
    }
}

答案 1 :(得分:2)

如果未调用此异常映射器(如John Ding的注释所示),请确保将其注册到ResourceConfig。

另外,请注意,当使用JacksonFeature(使用Jersey 2.x)时,它包含一个异常映射器,但是如果你自己注册它将优先。

以下是按包注册的示例。所以把JSONParseExceptionMapper放在“your.package.here”中它就会被拿起来。

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

对于原始问题,您还需要处理JsonMappingExceptionMapper。

答案 2 :(得分:1)

除了@ Perception的答案之外,缺少的部分是异常被吞噬而不被报告。您应该传递验证侦听器:

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

只需将此代码放入JAXB bean中即可。

答案 3 :(得分:0)

添加Perception答案的完整类示例

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();

     }
}

答案 4 :(得分:0)

另一个选项可能在ResourceConfig中,注册JsonParseExceptionMapper类。

寄存器(JsonParseExceptionMapper.class);

答案 5 :(得分:0)

在web.xml文件中提到的同一个包(或子包)中添加异常处理类