8

我在我的 Web 应用程序中使用 Jersey。发送到服务器的数据为 JSON 格式,在服务器端依次解组,获取的对象用于进一步处理。安全审计为这种方法提出了一些漏洞。

我的休息代码:

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

漫画豆:

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)

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

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

4

6 回答 6

17

注册一个异常映射器来处理 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();
    }
}
于 2013-02-13T12:56:21.033 回答
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 。

于 2014-08-18T20:12:20.837 回答
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 和您的所有设置中。

于 2017-03-01T19:23:05.940 回答
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();

     }
}
于 2014-03-11T12:36:03.043 回答
0

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

注册(JsonParseExceptionMapper.class);

于 2014-09-30T09:52:44.273 回答
0

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

于 2016-04-14T04:22:01.940 回答