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

Undertow(JBoss 7)在重定向时对URL编码的参数进行篡改/重新编码

龚德本
2023-03-14

在JBoss论坛上发布:https://developer.jboss.org/thread/280195

更新2019-06-26显然这现在被确认为Undertow中的错误,并在此处提交了拉取请求。

这是一个SSCCE。

我有一个非常简单的Servlet,除了打印参数值外,它什么都不做:

public class TestServlet extends HttpServlet{
    public void service(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {
        final String URL = req.getParameter("url");
        System.out.printf("url parameter read as: [%s]\n", URL);
    }
}

我的应用程序的web。xml配置为自动重定向http访问:

<web-app>
 ...
<security-constraint>
    <web-resource-collection>
        <web-resource-name>SECURE</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>
</web-app>

…我还(在我的独立完整配置文件中)在http侦听器的定义中设置了重定向套接字属性:

<http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>

如果我部署到JBoss EAP 7.1并在浏览器中输入以下URL(其中URL参数携带URL编码值“http://www.google.com"):

http://localhost:8082/get-parameter-test/min?url=http%3A%2F%2Fwww.google.com

…这是我在开发者控制台中看到的:

因此,在自动重定向后,我的代码无法获得url参数的正确值,我在日志文件中看到:

url parameter read as: [http%3A%2F%2Fwww.google.com]

然而,如果我部署到JBoss EAP 6.2并执行相同的操作,URL在重定向中不会损坏,一切正常:

这个答案表明,JBoss配置文件(standalong-full.xml)中undertow系统中的http侦听器和https侦听器配置中的解码url参数可能与此有关。这是错误的。我尝试了四种组合:

  • http侦听器:解码url和https侦听器:解码url
  • http侦听器:解码url=“false”和https侦听器:解码url=“true”
  • http侦听器:解码url=“true”和https侦听器:解码url=“false”
  • http侦听器:解码url=“true”和https侦听器:解码url=“true”

在所有情况下,从超文本传输协议重定向到https的302响应都具有以下标头:

<代码>位置:https://localhost:8445/get-参数测试?url=http%3A%2F%2Fwww。谷歌。com

也就是说,在所有情况下,URL都被损坏了(如果你愿意,可以称之为重新编码,它是损坏的AFAIAC)。这种行为根本没有理由,也不是EAP 6.2所做的。decode-url参数的值只影响servlet内的HttpServletRequest#getRequest方法的行为,它对重定向的URL没有任何影响。


共有2个答案

辛弘壮
2023-03-14

你的URL没有被破坏,它正在被重新编码。问题是在从http重定向到https时重新编码URL。您正在将编码的url参数传递给http,即。http://www.google.com.

http://www.google.com --encode--> http%3A%2F%2Fwww.google.com --re-encode--> http%253A%252F%252Fwww.google.com

在重新编码url时,“%”被编码为“%”。

要禁用此行为,您需要在侦听器中进行更改。有一个名为decode-url的属性可用于禁用/启用此行为。

decode-url:如果URL应该被解码。如果未设置为true,则URL中的百分比编码字符将保持不变。

有关下拖子系统的更多信息,请参阅以下链接。https://docs.jboss.org/author/display/WFLY/Undertow子系统配置

注意:此功能可能在JBoss 6.2上有效,因为在JBoss 6.2中,此配置的子系统称为WEB,在JBoss EAP 7中被Undertow取代

慕光霁
2023-03-14

更新2019-06-26显然,这现在被确认为Undertow中的一个bug,在这里提交了一个pull请求

这是最终对我有效的方法。首先,我从我的web.xml中删除了整个

<http-listener name="default" socket-binding="http" enable-http2="true"/>
<https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>

我认为上述内容正是JBoss EAP 7.1中现成的内容,因此无需更改。

然后我创建了一个过滤器并将其添加到<代码>

<rewrite name="http-to-https" redirect="true" target="https://%h:8445%U%q"/>
  • %h远程主机名
  • %U是请求的URL路径
  • %q是查询字符串(自动前缀如果存在)

我在这里找到了上述代码——我确信在其他地方有一个更规范的参考,但它们似乎有效。

最后,我在<代码>

<server name="default-server">
    <http-listener name="default" socket-binding="http" enable-http2="true"/>
    <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
    <host name="default-host" alias="localhost">
        <location name="/" handler="welcome-content"/>
        <filter-ref name="server-header"/>
        <filter-ref name="x-powered-by-header"/>
        <filter-ref name="http-to-https" predicate="equals(%p, 8082)"/>
        <http-invoker security-realm="ApplicationRealm"/>
    </host>
</server>

使用上述配置,请求被重定向而无需重新编码URL:

$ curl -I -L -k http://localhost:8082/get-parameter-test?url=http%3A%2F%2Fwww.google.com
HTTP/1.1 302 Found
Connection: keep-alive
Server: JBoss-EAP/7
Location: https://127.0.0.1:8445/get-parameter-test?url=http%3A%2F%2Fwww.google.com
Content-Length: 0
Date: Tue, 11 Jun 2019 17:43:23 GMT

HTTP/1.1 200 OK
Connection: keep-alive
X-Powered-By: Undertow/1
Server: JBoss-EAP/7
Content-Length: 0
Date: Tue, 11 Jun 2019 17:43:23 GMT

...参数从Java正确读取:

url parameter read as: [http://www.google.com]

无需在http/https侦听器中设置解码url,因为这是默认值。

注意:以上导致JBoss EAP 7.1发送302重定向。我不知道如何配置303或307重定向

上述方法的明显替代方法是使用HttpServletRequest#sendRedirect从应用程序代码以编程方式进行重定向。在这种情况下,您也不需要在http侦听器中重定向套接字。

显然,重定向套接字属性仅与

<代码>错误[io.undertow.request](默认任务14)UT005001:处理请求时发生异常:java。lang.IllegalState异常:UT010053:没有可用于重定向当前请求的机密端口 )。

但是,如果您同时具有<代码>

 类似资料:
  • 问题内容: 我需要修改现有的APK,修改源,然后重新编译。 我可以使用dex2jar或apktool对其进行反编译,效果很好 从jar文件中,我可以获取Java源代码(使用jd-gui) 然后我可以修改Java文件 但是现在我想知道如何重新编译java文件并将它们放回jar文件中!(jar部分应该很简单,主要问题似乎是如何为Android重新编译Java文件) 我知道另一种解决方案是使用apkto

  • 我试图通过参数在谷歌搜索,它的工作,当我搜索一个词,但一个我做空间它坏了我知道有一种方法来编码网址。 回溯: 还有一次,我用希伯来文写道: UnicodeEncodeError:“ascii”编解码器无法对位置14-18中的字符进行编码:序号不在范围内(128)

  • 我想为我的网站创建一个编码的网址。例如,对于这个URL:"http://google.com/index.html" 我想通过URL编码将此URL提供给客户端。

  • 我正在使用JSF2和PrimeFaces。我如何编写selectOneMenu,当用户更改菜单中的选项时,调用JSF导航将用户重定向到同一个页面,但参数不同?我只需要换颜色。 来自网址: MyView。xhtml:(无工作) ManagedBean:

  • 我们的代码使用Asyncresttemplate如下所示

  • 我试着在谷歌上搜索,找了一段时间,但没有找到任何解释如何做好这件事的地方 变量是firstname、lastname、social security number和weekly salary。