【问题标题】:Exception while dispatching incoming RPC call : encodedRequest cannot be empty调度传入 RPC 调用时出现异常:encodedRequest 不能为空
【发布时间】:2013-09-24 19:14:47
【问题描述】:

这里描述了类似的问题:GWT IllegalArgumentException: encodedRequest cannot be empty

我的 GWT 应用程序部署在 Tomcat6 中,它通过 Coyote/JK2 连接器与 Apache 链接。对于 SSO,我使用 mod_auth_sspi/1.0.4。

当我使用 IE8 时,页面不显示,但对于 Firefox 一切正常。在 Tomcat 日志中,我看到以下内容:

SEVERE: Exception while dispatching incoming RPC call
java.lang.IllegalArgumentException: encodedRequest cannot be empty
    at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:232)
    at org.spring4gwt.server.SpringGwtRemoteServiceServlet.processCall(SpringGwtRemoteServiceServlet.java:32)
    at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248)
    at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:643)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at gov.department.it.server.RequestInterceptorFilter.doFilter(RequestInterceptorFilter.java:90)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190)
    at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:311)
    at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:776)
    at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:705)
    at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:898)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
    at java.lang.Thread.run(Thread.java:619)

到目前为止我尝试了什么:

1) 找不到注册表项DisableNTLMPreAuth(恕我直言,这不是解决方案,因为在我的情况下,IE 8 被积极使用)。

2) 我已经安装并配置了 Native Windows Authentication Framework WAFFLE

web.xml:

...
<filter>
    <filter-name>NegotiateSecurityFilter</filter-name>
    <filter-class>waffle.servlet.NegotiateSecurityFilter</filter-class>
    <init-param>
        <param-name>waffle.servlet.spi.NegotiateSecurityFilterProvider/protocols</param-name>
        <param-value>NTLM</param-value>
    </init-param>
</filter>
...
<filter-mapping>
    <filter-name>NegotiateSecurityFilter</filter-name>
    <url-pattern>/my-app/*</url-pattern>
</filter-mapping>
...

但这并没有帮助。

3) 在worker.properties 中我设置了socket_keepalive=0,但也没有用-

worker.ajp13.type=ajp13
worker.ajp13.host=localhost
worker.ajp13.port=8009
worker.ajp13.lbfactor=50
worker.ajp13.cachesize=10
worker.ajp13.cache_timeout=600
worker.ajp13.socket_keepalive=0
worker.ajp13.socket_timeout=300

我还能尝试做什么?

【问题讨论】:

    标签: apache internet-explorer tomcat single-sign-on ntlm


    【解决方案1】:

    您在mod_auth_sspi 中重新发现了 7 岁的bug #1,多年来它影响了许多项目,挫败了许多开发人员,并造成了无数的工时浪费。然而它仍然没有解决,因为维护者doesn't consider it a bug。微软也没有针对旧版浏览器解决这个问题,因为有迹象表明 IE9 没有这个问题。

    原因

    这是由于 IE 试图“聪明”并发送零内容长度的 POST(我将其命名为 0POST 以尝试使其成为可索引的术语,以使那些在下一个重新发现它的人受益

    em> 7 年。)带有 NTLM 身份验证标头,预计会受到服务器的挑战。 IE 之前在该保护空间中经过身份验证时会执行此操作。所以它知道它会再次受到挑战。遗憾的是 mod_auth_sspi 不如 IE 聪明,所以当 0POST 到达时,服务器端会发生不好的事情,它会在没有受到挑战的情况下通过应用程序。除了有时即使在未受保护的区域也可能发生这种情况,如果它们位于需要身份验证的区域之下。 其他浏览器不会假装像IE一样聪明,也不会为了“性能”而尝试在第一次往返时节省几个字节,所以它们不会遇到这个问题。这是 Microsoft's explanation 的这种行为。

    可怕的解决方法

    在 Apache httpd.conf 中设置

    SSPIPerRequestAuth On
    

    这相当于您提到的DisableNTLMPreAuth IE 客户端修复,这对于大型用户组来说是不切实际的。此外,这也相当于削弱所有非 Apache 应用程序,这些应用程序可能能够处理 0POST。从字面上看,没有任何关于此设置的示例或其副作用在网络上进行了解释,因此我将这个 only link 包括在内,我发现它对此有所了解。无论如何,改变一个服务器端似乎是两害相权取其轻。虽然现在,通过更改服务器配置,您也削弱了所有其他访问该站点的无辜浏览器。

    此解决方法的问题在于,它强制每个请求都执行 SSPI 握手,这会导致大量额外的 401 流量并可能影响性能。出于性能考虑,NTLM 身份验证被视为“基于会话”而不是“基于请求”,这意味着握手仅在会话开始时发生。使用此设置时,您还应该设置过滤器以防止日志填满 401。另请注意,这需要启用 KeepAlive。

    我不确定您的设置是否与 WAFFLE 修复中描述的设置相同;他们像你一样使用 Apache 吗?我认为 WAFFLE 适用于 Tomcat,而前面有 Apache,所以 Apache 正在处理身份验证。您可能会考虑使用该设置而不是 Apache。如果您可以使用该设置,它可能是比此解决方法更好的选择,因为 WAFFLE 已明确说明 0POST 和 can handle it。作者在与您这样的 GWT 合作时拥有also discovered this gem。

    有趣的是,对于 jcifs,a fix for this very issue was posted 9 年前。作者后来还提供了excellent explanation

    过滤器中的代码检查所有 HTTP POST 请求并确定 如果它们包含 NTLM 类型 1 消息。如果请求包含 NTLM 类型 1 消息,过滤器以虚拟类型 2 消息响应 满足 IE 在提交任何内容之前重新协商 NTLM 的愿望 POST 数据。 然后浏览器应该以 NTLM 类型 3 响应 消息以及过滤器应该允许的发布数据 链接到 Web 应用程序的其余部分。

    如果您有兴趣,5 年前还为 mod_auth_sspi 创建了一个 simple patchSee diff 在作者自己的仓库中。我不确定我是否同意这种方法。它尝试检测 IE/0POST,而我认为正确的解决方法应该是检测客户端是否使用 NTLM 类型 1 标头请求身份验证,如在 jcifs 过滤器中。 (Type 1 简单来说就是握手的第一条消息)

    我想知道是否有人使用过mod_auth_sspi 的替代品,例如mod_auth_ntlm_winbind,并且他们是否没有表现出这种行为。如果你有,请发表评论。我们已经知道 WAFFLE 有效,但它不是 mod_auth_sspi 的替代品。

    另一种方法是忘记 NTLM 并使用 Kerberos (mod_auth_kerb),但许多人发现设置太复杂。 IE 在任何质询-响应方案上都会以这种方式运行,因此遏制身份验证可能会遇到相同的问题,因为在这两种情况下都会发生类似的 401 序列。但是作为一个不同的模块,它可能能够处理这个。

    最后,我应该提一下,这个按请求身份验证解决方法似乎还没有解决另一个问题。我没有在任何地方看到它讨论过,但我发现有时在 0POST 之后,服务器会等待很长时间,然后才会以(正确的)POST 的结果以最终的 200 响应进行响应。不过,这种长时间的延迟只发生在最后,而不是立即响应 0POST。一切顺利,握手完成,但服务器直到经过长时间的等待后才响应,我注意到这可疑地接近 90 秒,就像某种超时。这样做的实际结果是,当用户登录时,IE8 有时会挂起 90 秒等待服务器响应。我认为KeepAlive 可能会导致它,但它甚至没有在我的配置中明确定义,所以我假设它是 15 秒 Apache 默认值。但我确信这与 0POST 有关,因为它仅在成功的 0POST 身份验证握手之后发生。我们的服务器位于跨越防火墙的单独(2 路)受信任域中,因此可能与此有关。

    此问题的各种示例

    最搞笑的例子是 IE 的智能如何影响微软自己的产品!他们自己无法理解如何处理 IE 的行为,导致 ISA Server 2006 出现错误。

    【讨论】:

    • “因为有迹象表明 IE9 没有这个问题”——现在我们有了 2015 年,而 IE11 显然仍然这样做......
    猜你喜欢
    • 1970-01-01
    • 2012-09-04
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-01
    相关资源
    最近更新 更多