当前位置: 首页 > 知识库问答 >
问题:

泽西岛在使用容器请求上下文后为每个呼叫抛出 NPE。

管杜吟
2023-03-14

我有一个RESTfulendpoint,我通过一个定制的ContainerRequestFilter用一个简单的授权检查来保护它。过滤器检查HTTP会话中包含的所有信息是否正确,如果不正确,则执行以下操作:

requestContext.abortWith(Response.status(Response.Status.FORBIDDEN)
.entity("Forbidden").build());

这一切都很好。奇怪的是,当我再次发出相同的GET请求时,泽西服务器报告了一个NPE并且没有返回任何东西。

NPE 堆栈跟踪:

Jul 20, 2016 5:27:53 PM org.glassfish.jersey.server.ServerRuntime$Responder writeResponse
SEVERE: An I/O error has occurred while writing a response message entity to the container output stream.
java.lang.IllegalStateException: The output stream has already been closed.
    at org.glassfish.jersey.message.internal.CommittingOutputStream.setStreamProvider(CommittingOutputStream.java:147)
    at org.glassfish.jersey.message.internal.OutboundMessageContext.setStreamProvider(OutboundMessageContext.java:803)
    at org.glassfish.jersey.server.ContainerResponse.setStreamProvider(ContainerResponse.java:372)
    at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:694)
    at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:444)
    at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:434)
    at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:329)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
    at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:384)
    at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:224)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
    at java.lang.Thread.run(Thread.java:745)

发生了什么?我不想关闭输出流。我只需要一个方法向请求者返回http返回代码消息。

共有3个答案

金兴朝
2023-03-14

您不需要使用requestContext。过滤器方法中的abortWith()。相反,请执行以下操作。

    String authCredentials = containerRequest.getHeaderString(HttpHeaders.AUTHORIZATION);

从您的REST客户端[browser/postman/SoapUI/jersey客户端程序]发送的头将采用“基本编码字符串”的格式。使用< code>java.util.Base64可以轻松解码编码的字符串。在服务器端解码后,字符串的格式将是username:password。使用< code > string . split(":");将用户名和密码分开。开始验证。如果验证变为false,则从您在此处重写的< code > ContainerRequestFilter 的Filter方法中抛出< code > WebApplicationException 。

衡子琪
2023-03-14

如前所述,问题出在已经设置的静态ACCESS_DENIED响应上。

private static final Response ACCESS_DENIED = Response.status(Response.Status.UNAUTHORIZED).entity("Accesso não Autorizado").build();

因此,替换为:

requestContext.abortWith(ACCESS_DENIED)

requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Accesso não Autorizado").build());
白修谨
2023-03-14

万一有人会遇到同样的问题,我这里有答案:你不能重复使用响应!输出流编写器的实例绑定到请求,一旦您在中止使用它,流将被永久提交。因此,它不能再用于发送响应。

您需要从filter()方法中初始化一个新的Request。

简单来说,不要使用这样的构造:

 private static final Response ACCESS_FORBIDDEN = Response.status(Response.Status.FORBIDDEN)
            .entity("Access blocked for all users !!").build();

顺便说一句,我在这里找到了这段破碎的代码:http://howtodoinjava.com/jersey/jersey-rest-security/因此,在实现此Request estFilter时要小心。

 类似资料:
  • 在Jersey 2中,我可以将一个定制的、请求特定的值注入到我的资源中吗?具体来说,我想注入一个< code>MyThing,它可以从我的自定义安全上下文< code>MySecurityContext中派生出来。我想直接注入< code>MyThing来使代码变得干净。 有什么办法可以做到这一点吗?根据这个问题,它不能使用尽管本文和此示例表明它可能是可能的。 使用身份验证筛选器,我可以使用以下代

  • 我有灰熊提供的球衣。 我有一个实现类。但是,为所有传入请求创建一次此类。因此,这样做: 为空。我可以将上下文注入到被调用的实际endpoint中,但这相当粗糙和丑陋,对我来说真的没有用;因为我希望记录各种请求。理想情况下,希望在请求的ResponseFilter端找到这个对象。 必须有一种简单的方法来做到这一点。到目前为止,我看到的所有问题/答案都不适用于灰熊,或者注入了RESTendpoint调

  • 我试图理解异步响应在Jersey上的工作方式。我阅读了新泽西文档(https://jersey.java.net/documentation/latest/async.html)的第10章,但它对我的问题没有帮助。这里关于stackoverflow的研究也没有得出令人满意的答案(这一点我可以理解)。 我试图做的与本文中的一个问题类似(使用http状态202进行异步操作)。我想使用HTML表单文档将

  • 我有一个基于令牌的用户身份验证的Jersey REST应用程序。当请求传入时,会创建一个自定义的对象,并将其作为一个属性添加到 的用法,我想知道是否可以使用injection将这个< code>RestContext注入到我的资源和其他过滤器中(例如,我有一个过滤器,它从< code>RestContext中创建一个< code>SecurityContext),但是我找不到答案。一般来说,我如何

  • 我目前使用的是球衣 我现在要做的是设置泽西,这样当查询参数进来时(比如缩进),我可以告诉Jackson以“更漂亮的格式,也就是缩进”序列化JSON。您可以通过使用SerializationConfig.Feature.INDENT_OUTPUT配置JSON映射器来轻松地告诉Jackson这样做。 问题是,我如何在每个请求的基础上获取一个queryparam并使用它来修改Jackson的输出?

  • 我使用客户机对一个API进行REST调用,该API返回mulipart中的一个Json和一个PDF文件作为响应的第一和第二部分。 使用上面的客户端解析这个多部分响应的正确方法是什么?