2013-02-13 104 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豆和你的所有設置剛落,該代碼。