1

这里描述了类似的问题: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

网页.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

我还能尝试做什么?

4

1 回答 1

8

您重新发现了 7 年前的bug #1mod_auth_sspi它影响了许多项目,使许多开发人员感到沮丧,并造成了数年来的无数工时浪费。然而它仍然没有解决,因为维护者不认为它是一个错误。微软也没有针对旧版浏览器解决这个问题,因为有迹象表明 IE9 没有这个问题。

原因

这是由于 IE 试图变得“聪明”并发送零内容长度的 POST 引起的(我将其命名0POST为尝试使其成为可索引的术语,以使那些在下一个重新发现它的人受益7 年。)带有 NTLM 身份验证标头,预计会受到服务器的挑战。IE 之前在该保护空间中经过身份验证时会执行此操作。所以它知道它会再次受到挑战。遗憾的是 mod_auth_sspi 不如 IE 聪明,所以当 0POST 到达时,服务器端会发生不好的事情,它会在没有受到挑战的情况下通过应用程序。除了有时即使在未受保护的区域也可能发生这种情况,如果它们位于需要身份验证的区域之下。其他浏览器不会假装像IE一样聪明,也不会为了“性能”而尝试在第一次往返时节省几个字节,所以它们不会遇到这个问题。这是微软对此行为的解释。

可怕的解决方法

在 Apache httpd.conf 中设置

SSPIPerRequestAuth On

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

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

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

有趣的是,对于 jcifs,这个问题的修复是在 9 年前发布的。作者后来也提供了很好的解释:

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

如果您有兴趣,5 年前还为 mod_auth_sspi 创建了一个简单的补丁。请参阅作者自己的仓库中的差异。我不确定我是否同意这种方法。它尝试检测 IE/0POST,而我认为正确的解决方法应该是检测客户端是否使用 NTLM 类型 1 标头请求身份验证,如 jcifs 过滤器中。(类型 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 出现错误。

于 2013-10-11T03:33:33.670 回答