【问题标题】:Preserving + (Plus Sign) in URLEncoded Http Post request在 URLEncoded Http Post 请求中保留 +(加号)
【发布时间】:2018-11-29 20:01:36
【问题描述】:

我有这个用于登录请求的函数。

private login(params: LoginParams): Promise<any> {
    const loginHeaders: HttpHeaders = new HttpHeaders()
        .set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
        .set('site', 'first');

    const loginCredentials = new HttpParams()
        .set('j_username', params.username)
        .set('j_password', params.password);

    const requestUrl = this.appConfig.baseUrl + 'restoftheurl';

    return this.http
        .post(requestUrl, loginCredentials.toString(),
            {headers: loginHeaders, responseType: 'text'})
        .toPromise();
  }

如果密码中有一个加号 (+),它会被编码为一个空格符号,然后请求失败,因为它是一个错误的凭据。如何保留加号?我做错了什么?

【问题讨论】:

标签: angular http urlencode


【解决方案1】:

这也是一个 Angular 问题 (@angular/common/http)

它将原始 + 符号解释为空格的替换。

你可以将HttpParameterCodec实现成一个简单的编码器,例如:

import {HttpParameterCodec} from "@angular/common/http";
export class HttpUrlEncodingCodec implements HttpParameterCodec {
    encodeKey(k: string): string { return standardEncoding(k); }
    encodeValue(v: string): string { return standardEncoding(v); }
    decodeKey(k: string): string { return decodeURIComponent(k); }
    decodeValue(v: string) { return decodeURIComponent(v); }
}
function standardEncoding(v: string): string {
    return encodeURIComponent(v);
}

然后用它来正确编码:

const headers = new HttpHeaders({'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'});
const params = new HttpParams({encoder: new HttpUrlEncodingCodec()});
http.post(url, params, {headers: this.headers});

【讨论】:

  • 到处寻找解决方案,这个解决方案奏效了。非常感谢
  • 我认为你可以使用HttpUrlEncodingCodec 而不是自己实现。
  • 更正:内置的HttpUrlEncodingCodec 不起作用,因为它还会用空格替换+
【解决方案2】:

只需使用encodeURIComponent 对密码进行编码,然后再发送即可。

private login(params: LoginParams): Promise < any > {

  ...

  const loginCredentials = new HttpParams()
    .set('j_username', params.username)
    .set('j_password', encodeURIComponent(params.password));

  ...
}

注意:在您的 API 端,您必须使用 decodeURIComponent(yourPasswordParam) 来获取实际密码。

更新:

就在这里尝试一下,看看它在编码方面的作用:

var encodedUsername = encodeURIComponent('mclovin+');
console.log('Encoding Username gives: ', encodedUsername);
console.log('NOT mclovin%252B');

var encodedPassword = encodeURIComponent('fogell+');
console.log('Encoding Password gives: ', encodedPassword);
console.log('NOT fogell%252B');

【讨论】:

  • 我以前试过这个。不幸的是,它对凭证进行了双重编码,最终作为错误的凭证请求失败。示例:用户名:mclovin+ 和密码:fogel+ 编码为 mclovin%252B 和 fogell%252B。这可能与他的评论中提到的 Angular 错误 @jonrsharpe 有关。
  • 这很奇怪。不知道为什么它对凭据进行双重编码。你用的是哪个浏览器?
  • 可能是因为 Angular 本身在不应该对 HttpParams 进行编码时?我使用 Chrome,顺便说一句
  • Angular HttpParams 默认编码器已损坏...它无法正确编码加号,问题:github.com/angular/angular/issues/33728github.com/angular/angular/issues/18261
【解决方案3】:

如果您尝试将其作为 URL 的一部分发送,则必须使用 encodeURIComponent 对其进行编码。

看到您的代码,您将在 HTTP 参数中添加密码和用户名,这些参数将显示在请求 URL 中。

如果您不想将用户名和密码显示为 url 查询字符串的一部分,您可以将其作为 http 调用的请求正文发送,您不需要这样做encodeURIComponent

前:console.log(encodeURIComponent('?x=test'));

console.log(encodeURIComponent('+test'));

【讨论】:

  • 不幸的是,它对凭据进行了双重编码,最终作为错误的凭据请求失败。这可能与他的评论中提到的 Angular 错误 @jonrsharpe 有关。
  • 您使用的是哪个浏览器?我可以在 Chrome 中看到它编码一次
  • 这不是 JavaScript 问题。显然,这是一个 Angular 问题。顺便说一句,我使用 Chrome!
  • 是的,我现在看到了这个错误:github.com/angular/angular/issues/18261。人们已经为此提交了解决方法,您应该能够遵循它。
  • 我会尝试这些。在这里发布之前我不知道这个错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-08
  • 1970-01-01
  • 2014-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多