【问题标题】:Angular HttpClient post not workingAngular HttpClient 帖子不起作用
【发布时间】:2018-05-01 19:47:04
【问题描述】:

我正在更改我的代码以将我的 http api 从“@angular/http”更改为“@angular/common/http”。我的大多数请求都可以正常工作,但是无论我多么努力,为我带来刷新令牌的身份验证都无法正常工作......请看我的代码如下:

    const headerHttp = new HttpHeaders();
    headerHttp.set('Content-Type', 'application/x-www-form-urlencoded');
    headerHttp.set('Authorization', 'Basic YW5ndWxhcjphbmd1bGFy');

    this.clientHttp.post(this.oauthTokenUrl,
      { username: user, password: pwd , grant_type: 'password' },
      {  headers: headerHttp, withCredentials: true })
        .subscribe(
      res => {
         console.log(res);
      },
      err => {
         console.log('Error occured');
      }
    );

但是参数(用户名、密码和grant_type)没有到达服务器并且弹出一个输入屏幕。

这是我的请求的结果,使用'@angular/http':

图片 1

这是我的请求不起作用的结果,我在上面放的代码。

图片 2

EDIT 1 - 验证输入屏幕不再弹出,代码如下。

const _params = new HttpParams()
.set('grant_type', 'password')
.set('username', usuario)
.set('password', senha );

const _headers = new HttpHeaders()
  .set('Authorization', 'Basic YW5ndWxhcjphbmd1bGFy')
  .set('Content-Type', 'application/x-www-form-urlencoded');

const httpOptions = {
  headers: _headers,
  params: _params,
  withCredentials: true
};

this.clientHttp.post<String>(this.oauthTokenUrl, httpOptions).subscribe(
res => {
  console.log(res);
},
err => {
  console.log('Error occurred', err);
});

是我以前的代码,并且工作正常。

    const headers = new Headers();

    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    headers.append('Authorization', 'Basic YW5ndWxhcjphbmd1bGFy');

    const body = `username=${usuario}&password=${senha}&grant_type=password`;

    return this.http.post(this.oauthTokenUrl, body,
        { headers, withCredentials: true })
      .toPromise()
      .then(response => {
        this.armazenarToken(response.json().access_token);
      })
      .catch(response => {
        if (response.status === 400) {
          const responseJson = response.json();

          if (responseJson.error === 'invalid_grant') {
            return Promise.reject('Usuário ou senha inválida!');
          }
        }

        return Promise.reject(response);
      });
  }

但是现在 HttpClient 创建一个“请求有效负载”而不是“表单数据”。为什么? servlet 无法像读取“表单数据”一样读取“请求有效负载”,因此无法正确进行身份验证。

编辑 2 - 解决方案

经过大量尝试后,我根据@mtpultz 的建议提出了一个新的 FormData() 。

const params = new HttpParams()
.set('grant_type', 'password')
.set('username', user)
.set('password', pwd );

const headers = new HttpHeaders()
  .set('Authorization', 'Basic xpto')
  .set('Content-Type', 'application/x-www-form-urlencoded');

const httpOptions = {
  headers: headers,
  params: params,
  withCredentials: true
};

//The line works ( Requisition with Form Data, like IMAGE 1 above )
this.httpClient.post<Response>(this.oauthTokenUrl,  new FormData(), httpOptions )

//The line, without new FormData(), doesn't work.  ( Requisition with Request Payload, like IMAGE 2 above )
this.httpClient.post<Response>(this.oauthTokenUrl,  httpOptions )

【问题讨论】:

  • 我认为您需要提供更多的周边代码才能弄清楚这一点,因为您所做的似乎是正确的。
  • @mtpultz,我试图在不改变结果的情况下删除代码的所有环境,甚至是 HttpInterceptor。但是我添加了更多信息,问题对我来说似乎更清楚了。不幸的是,不是解决方案...... :-( Tks!
  • 是的,您的原始代码肯定不会工作,因为HttpClient 请求和响应是不可变的,所以headers.append(...) 实际上返回了一个副本,您需要通过执行headers = headers.append(...) 来存储它,但是你没有存储它,如果你这样做,headers 需要是 let 而不是 const

标签: angular rest http oauth-2.0


【解决方案1】:

将您的代码放入stackblitz example 中,当您在控制台中查看它时,这似乎发送Form Data 而不是Request Payload。我相信它正确发送的原因是基于本地表单提交表单字段名称/值对作为查询字符串,将它们添加为参数模仿。

  public test() {
    const headers = new HttpHeaders({
      'Content-Type': 'application/x-www-form-urlencoded',
      'Authorization': 'Basic YW5ndWxhcjphbmd1bGFy'
    });
    const params = new HttpParams()
      .set('username', 'test@example.com')
      .set('password', 'secret')
      .set('grant_type', 'password');
    const options = {
      headers,
      params,
      withCredentials: true
    };
    this.httpClient.post('https://reqres.in/api/example', null, options)
      .subscribe(response => console.log(response));
  }

另外,我建议使用Observables,而不是将您的回复转换为Promises。如果您对 Observables 不满意,但很快就可以学习一些处理 HTTP 请求的基础知识。

【讨论】:

  • 最后一个版本,没有“新的 FormData()”,不起作用。谢天谢地,您的第一个解决方案仍然有效。 :-) 代码与上面相同,加上“withCredentials: true”。我再次编辑添加“new FormData()”作为解决方案,即使我并不完全清楚这种行为背后的原因。
  • 我不认为传递new FormData() 使它正常工作。您应该能够通过null 并获得相同的结果。我认为这是可行的,因为提交时的原生表单会将表单字段名称/值对作为查询字符串添加到请求中。因此,通过将它们添加为参数会产生与本地表单提交相同的查询字符串结果。
  • 你能告诉我这是否与我在这里遇到的问题相似吗? github.com/elfelround/pangeanic/blob/…
  • 您只提供代码,但不解释问题。我会说不,因为您没有使用 HttpParams。你有错误吗?
猜你喜欢
  • 2019-05-06
  • 2018-01-25
  • 2018-12-21
  • 1970-01-01
  • 2019-10-05
  • 1970-01-01
  • 2017-12-31
  • 2018-12-15
  • 2018-12-04
相关资源
最近更新 更多