Angular HttpClient 帖子不起作用

San*_*gão 5 rest http oauth-2.0 angular

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

\n\n
    const headerHttp = new HttpHeaders();\n    headerHttp.set(\'Content-Type\', \'application/x-www-form-urlencoded\');\n    headerHttp.set(\'Authorization\', \'Basic YW5ndWxhcjphbmd1bGFy\');\n\n    this.clientHttp.post(this.oauthTokenUrl,\n      { username: user, password: pwd , grant_type: \'password\' },\n      {  headers: headerHttp, withCredentials: true })\n        .subscribe(\n      res => {\n         console.log(res);\n      },\n      err => {\n         console.log(\'Error occured\');\n      }\n    );\n
Run Code Online (Sandbox Code Playgroud)\n\n

但参数(用户名、密码和 grant_type )未到达服务器,并且弹出输入屏幕。

\n\n

在此输入图像描述

\n\n

这是我的请求的结果,与 \'@angular/http\' 一起工作:

\n\n

图片 1\n在此输入图像描述

\n\n

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

\n\n

图片 2\n在此输入图像描述

\n\n

编辑 1 - 身份验证输入屏幕不再弹出,代码如下。

\n\n
const _params = new HttpParams()\n.set(\'grant_type\', \'password\')\n.set(\'username\', usuario)\n.set(\'password\', senha );\n\nconst _headers = new HttpHeaders()\n  .set(\'Authorization\', \'Basic YW5ndWxhcjphbmd1bGFy\')\n  .set(\'Content-Type\', \'application/x-www-form-urlencoded\');\n\nconst httpOptions = {\n  headers: _headers,\n  params: _params,\n  withCredentials: true\n};\n\nthis.clientHttp.post<String>(this.oauthTokenUrl, httpOptions).subscribe(\nres => {\n  console.log(res);\n},\nerr => {\n  console.log(\'Error occurred\', err);\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
    const headers = new Headers();\n\n    headers.append(\'Content-Type\', \'application/x-www-form-urlencoded\');\n    headers.append(\'Authorization\', \'Basic YW5ndWxhcjphbmd1bGFy\');\n\n    const body = `username=${usuario}&password=${senha}&grant_type=password`;\n\n    return this.http.post(this.oauthTokenUrl, body,\n        { headers, withCredentials: true })\n      .toPromise()\n      .then(response => {\n        this.armazenarToken(response.json().access_token);\n      })\n      .catch(response => {\n        if (response.status === 400) {\n          const responseJson = response.json();\n\n          if (responseJson.error === \'invalid_grant\') {\n            return Promise.reject(\'Usu\xc3\xa1rio ou senha inv\xc3\xa1lida!\');\n          }\n        }\n\n        return Promise.reject(response);\n      });\n  }\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

编辑 2 - 解决方案

\n\n

经过大量尝试后,使它起作用的是我按照 @mtpultz 建议放置的新 FormData() 。

\n\n
const params = new HttpParams()\n.set(\'grant_type\', \'password\')\n.set(\'username\', user)\n.set(\'password\', pwd );\n\nconst headers = new HttpHeaders()\n  .set(\'Authorization\', \'Basic xpto\')\n  .set(\'Content-Type\', \'application/x-www-form-urlencoded\');\n\nconst httpOptions = {\n  headers: headers,\n  params: params,\n  withCredentials: true\n};\n\n//The line works ( Requisition with Form Data, like IMAGE 1 above )\nthis.httpClient.post<Response>(this.oauthTokenUrl,  new FormData(), httpOptions )\n\n//The line, without new FormData(), doesn\'t work.  ( Requisition with Request Payload, like IMAGE 2 above )\nthis.httpClient.post<Response>(this.oauthTokenUrl,  httpOptions )\n
Run Code Online (Sandbox Code Playgroud)\n

mtp*_*ltz 4

将您的代码放入stackblitz 示例中,这似乎会发送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));
  }
Run Code Online (Sandbox Code Playgroud)

另外,我建议使用Observables而不是将您的回复转换为Promises. 如果您还不熟悉Observables,那么不需要很长时间就可以学习一些处理 HTTP 请求的基础知识。