2013-02-13 34 views
5

我在我的Web应用程序中使用Jersey。发送到服务器的数据采用JSON格式,然后在服务器端解组,并将获得的对象用于进一步处理。安全审计提出了这种方法的一些弱点。如何在解组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: [email protected]; 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) 

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

我的问题是我如何处理这个异常,并返回一个适当的响应,而不是一个堆栈跟踪用户。请指教。

回答

14

注册一个例外映射器来处理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(); 
    } 
} 
+0

我真的不明白如何使用@Provider语法。我可以使用它来处理以下情形:当Map为空而不是{}时,Unruly API返回[]。似乎从上面,我可以映射此异常并处理它? – deepwinter 2014-01-30 03:10:44

+1

我无法为我的生活得到这个在泽西2.13工作。啊。 – 2015-01-09 05:47:39

+0

我们正在使用CXF,但无论如何,这工作。谢谢! – fool4jesus 2016-05-02 17:01:21

0

添加感知答案

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

    } 
} 
+0

这不会被调用,我还需要做什么? – 2014-08-08 22:37:58

1

的满级的例子。如果该异常映射器不会被调用(如约翰·丁的评论注明),确保你已经注册了你的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。

0

其他选项可能在ResourceConfig中,注册JsonParseExceptionMapper类。

register(JsonParseExceptionMapper.class);

0

添加在web.xml文件

1

除了@感知的答复中提到同一包(或子包)的异常处理类,缺少的部分是例外得到吞咽并没有报道。你应该通过一个验证侦听:

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豆和你的所有设置刚落,该代码。