使用新的Spring UriComponentsBuilder进行URL编码

tic*_*ock 24 spring

我正在尝试使用spring的UriComponentsBuilder来生成一些用于oauth交互的URL.查询参数包括诸如回调URL和其中包含空格的参数值之类的实体.

试图使用UriComponentBuilder(因为现在不推荐使用UriUtils)

UriComponentsBuilder urlBuilder = UriComponentsBuilder.fromHttpUrl(oauthURL);
urlBuilder.queryParam("client_id", clientId);
urlBuilder.queryParam("redirect_uri", redirectURI);
urlBuilder.queryParam("scope", "test1 test2");

String url = urlBuilder.build(false).encode().toUriString();
Run Code Online (Sandbox Code Playgroud)

不幸的是,虽然scope参数中的空格已成功替换为'+',但redirect_uri参数根本不是url编码的.

例如,

redirect_uri=https://oauth2-login-demo.appspot.com/code
Run Code Online (Sandbox Code Playgroud)

应该结束了

redirect_uri=https%3A%2F%2Foauth2-login-demo.appspot.com%2Fcode
Run Code Online (Sandbox Code Playgroud)

但没有动过.潜入代码,特别是org.springframework.web.util.HierarchicalUriComponents.Type.QUERY_PARAM.isAllowed(c):

if ('=' == c || '+' == c || '&' == c) {
  return false;
}
else {
  return isPchar(c) || '/' == c || '?' == c;
}
Run Code Online (Sandbox Code Playgroud)

明确地允许':'和'/'字符,这不应该是口香糖.它必须做一些其他类型的编码,虽然对于我的生活,我无法想象什么.我在这里吠叫错了树吗?

谢谢

sim*_*onh 21

UriComponentsBuilder根据RFC 3986编码您的URI ,第3.4节关于URI的'query'组件是特别注意的.

在'query'组件中,​​允许使用字符'/'和':',并且不需要转义.

以'/'字符为例:'query'组件(由未转义的'?'和(可选)'#'字符明确分隔),不是分层的,'/'字符没有特殊含义.所以它不需要编码.

  • 这是不正确的,因为`&`和其他具有含义的字符也不会转义。UriComponentsBuilder不会对查询参数进行url编码。 (2认同)
  • 你可能会这么想,但事实并非如此。尝试一下看看。 (2认同)
  • 我报告了toUriString()行为后,如果没有变量存在,Spring开发人员会立即将其修复为使用build()。encode()。toUriString()(原始行为)。现在,查询参数(例如“ {}”)将正确编码。https://jira.spring.io/browse/SPR-17630 (2认同)

Bla*_*ack 15

根据我的理解,UriComponentsBuilder不会自动编码查询参数,只是它实例化的原始HttpUrl.换句话说,您仍然需要显式编码:

String redirectURI= "https://oauth2-login-demo.appspot.com/code";
urlBuilder.queryParam("redirect_uri", URLEncoder.encode(redirectURI,"UTF-8" ));
Run Code Online (Sandbox Code Playgroud)

  • 嗯..这不是非常有用.这很奇怪,因为它是一个URL构建器,你可以添加查询参数,然后构建,然后编码.我原以为它正在为我建立一个安全的URL.如果没有使用URL编码,添加查询参数的重点是什么? (8认同)
  • UriComponentsBuilder包含一个encode()方法,我认为它将编码url和查询参数. (3认同)
  • 它对您传递给它的 *URL* 进行编码,但不是每个查询参数 (2认同)
  • 我同意,并且会像你一样假设。也许设计者有一些理由不隐式编码参数,但也可能没有 (2认同)