HTTP POST - 如何发送 Authorization 头部?

59

如何在Angular2 RC6中为你的http请求添加头信息? 我有以下代码:

login(login: String, password: String): Observable<boolean> {
    console.log(login);
    console.log(password);
    this.cookieService.removeAll();
    let headers = new Headers();
    headers.append("Authorization","Basic YW5ndWxhci13YXJlaG91c2Utc2VydmljZXM6MTIzNDU2");
    this.http.post(AUTHENTICATION_ENDPOINT + "?grant_type=password&scope=trust&username=" + login + "&password=" + password, null, {headers: headers}).subscribe(response => {
      console.log(response);
    });
    //some return
}
问题是,Angular没有添加授权头。相反,在请求中我可以看到以下附加标头:
Access-Control-Request-Headers:authorization
Access-Control-Request-Method:POST

并在 Accept-Encoding 中添加了 sdch:

Accept-Encoding:gzip, deflate, sdch
很遗憾,没有授权标头。我应该如何正确添加它? 我的代码发送的整个请求如下所示:
OPTIONS /oauth/token?grant_type=password&scope=trust&username=asdf&password=asdf HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: POST
Origin: http://localhost:3002
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Access-Control-Request-Headers: authorization
Accept: */*
Referer: http://localhost:3002/login
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,pl;q=0.6

1
你尝试过提供自己的请求选项吗?https://dev59.com/JVsW5IYBdhLWcg3w66qH#35047978 - Supamiu
@Supamiu 很遗憾,这个解决方案不起作用。我尝试了: this.http._defaultOptions.headers.set('Authorization', 'Basic YW5ndWxhci13YXJlaG91c2Utc2VydmljZXM6MTIzNDU2');但是得到了相同的结果。 - Maciej Treder
2
你在问题中展示的请求是 OPTIONS 预检请求,请问你能否添加 POST 请求?(应该紧随此请求在你的网络选项卡中) - Supamiu
请勿重复提交问题,这个问题已经在Stack Overflow上有了解答。 - Skyware
可能是Angular 2基本身份验证不起作用的重复问题。 - Swanand Taware
7个回答

34

好的。我找到了问题。

问题并不在Angular方面。说实话,根本没有任何问题。

导致我无法成功执行请求的原因是我的服务器应用程序没有正确处理OPTIONS请求。

为什么是OPTIONS而不是POST?我的服务器应用程序位于不同的主机上,然后是前端。由于CORS,我的浏览器将POST转换为OPTION: http://restlet.com/blog/2015/12/15/understanding-and-using-cors/

通过这个答案的帮助: Standalone Spring OAuth2 JWT Authorization Server + CORS

我在我的服务器端应用程序上实施了适当的过滤器。

感谢@Supamiu - 他指出我根本没有发送POST。


13
如果一切顺利,它会通过发送 OPTIONS 请求来进行预检,并发送 POST 请求。它不会用 OPTIONS 替换 POST - Oskar

18

您需要的是RequestOptions。

 let headers = new Headers({'Content-Type': 'application/json'});  
 headers.append('Authorization','Bearer ')
 let options = new RequestOptions({headers: headers});
 return this.http.post(APIname,body,options)
  .map(this.extractData)
  .catch(this.handleError);

要了解更多,请查看此链接


10

我相信在订阅结果之前,您需要对其进行映射。您可以像这样配置它:

  updateProfileInformation(user: User) {
    var headers = new Headers();
    headers.append('Content-Type', this.constants.jsonContentType);

    var t = localStorage.getItem("accessToken");
    headers.append("Authorization", "Bearer " + t;
    var body = JSON.stringify(user);

    return this.http.post(this.constants.userUrl + "UpdateUser", body, { headers: headers })
      .map((response: Response) => {
        var result = response.json();
        return result;
      })
      .catch(this.handleError)
      .subscribe(
      status => this.statusMessage = status,
      error => this.errorMessage = error,
      () => this.completeUpdateUser()
      );
  }

问题的关键不在于如何处理HTTP响应,而在于如何向请求添加适当的标头。我当然检查了你的建议 - 它不起作用,发送的标头仍然相同。 - Maciej Treder
你是否对HTTP请求进行了额外的配置? - Maciej Treder
哎呀...在我的端上它不起作用...不知道为什么...这是我的http版本:"@angular/http": "^2.0.0-rc.6",你确定你的版本一样吗? - Maciej Treder
你能给我展示一下你的请求发送了哪些头部吗? - Maciej Treder
1
headers.append("Authorization", "Bearer " + t); 这行代码缺少右括号。 - Joyal
显示剩余3条评论

6

如果你和我一样,正在盯着看起来像这样的Angular/Ionic TypeScript代码:

  getPdf(endpoint: string): Observable<Blob> {
    let url = this.url + '/' + endpoint;
    let token = this.msal.accessToken;
    console.log(token);
    return this.http.post<Blob>(url, {
      headers: new HttpHeaders(
        {
          'Access-Control-Allow-Origin': 'https://localhost:5100',
          'Access-Control-Allow-Methods': 'POST',
          'Content-Type': 'application/pdf',
          'Authorization': 'Bearer ' + token,
          'Accept': '*/*',
        }),
        //responseType: ResponseContentType.Blob,
      });
  }

当你在设置选项时,可能会发现它们似乎不存在...

如果像我一样,从复制/粘贴get开始编写此post,那么...

请改为:

  getPdf(endpoint: string): Observable<Blob> {
    let url = this.url + '/' + endpoint;
    let token = this.msal.accessToken;
    console.log(token);
    return this.http.post<Blob>(url, null, { //  <-----  notice the null  *****
      headers: new HttpHeaders(
        {
          'Authorization': 'Bearer ' + token,
          'Accept': '*/*',
        }),
        //responseType: ResponseContentType.Blob,
      });
  }

1
Access-Control headers are set by the server, not the client as is Content-Type - rism

3

我曾经遇到过同样的问题。这是我的解决方法,使用了Angular文档和Firebase令牌:

getService()  {

const accessToken=this.afAuth.auth.currentUser.getToken().then(res=>{
  const httpOptions = {
    headers: new HttpHeaders({
      'Content-Type':  'application/json',
      'Authorization': res
    })
  };
  return this.http.get('Url',httpOptions)
    .subscribe(res => console.log(res));
}); }}

2
这是对问题的详细答复:
将数据从Angular侧传入HTTP头(请注意,在应用程序中我使用的是 Angular4.0+)。
有多种方法可以将数据传递到标题中。语法不同,但意义相同。
// Option 1 
 const httpOptions = {
   headers: new HttpHeaders({
     'Authorization': 'my-auth-token',
     'ID': emp.UserID,
   })
 };


// Option 2

let httpHeaders = new HttpHeaders();
httpHeaders = httpHeaders.append('Authorization', 'my-auth-token');
httpHeaders = httpHeaders.append('ID', '001');
httpHeaders.set('Content-Type', 'application/json');    

let options = {headers:httpHeaders};


// Option 1
   return this.http.post(this.url + 'testMethod', body,httpOptions)

// Option 2
   return this.http.post(this.url + 'testMethod', body,options)

在调用中,您可以像下面的图像中所示找到作为标头传递的字段: enter image description here 但是,如果您遇到以下问题...(您可能需要更改后端/WebAPI侧)
  • 响应预检请求未通过访问控制检查:请求的资源上没有“Access-Control-Allow-Origin”标头。因此,来自“http://localhost:4200”的源不被允许访问

  • 预检响应没有HTTP ok状态。

请查看我的详细答案https://stackoverflow.com/a/52620468/3454221

1
如果您是一名Ruby on Rails开发人员,遇到类似的问题,这是由于您后端的配置:特别是在API模式下。所以,使用安装了gem 'rack-cors'的方法。
前往app/config/cors.rb文件。
请确保在修改此文件时重新启动服务器。
Rails.application.config.middleware.insert_before 0, Rack::Cors do
   allow do
     origins 'domain_name:port or just use *'

     resource '*',
       headers: :any,
       methods: [:get, :post, :put, :patch, :delete, :options, :head],
       credentials: true
   end
 end

在您的SessionController中,用户登录验证后插入以下行(假设您正在使用gem'jwt'):
the *credentials:true行就可以完成此操作。

token = user.generate_jwt
response.headers['Authorization'] = token

generate_jwt是在User模型中调用的方法,它用于生成JSON Web Token。

JWT.encode(id, key, alogrithm)

如果您使用Django,这已经为您处理了,您只需要使用已安装的应用程序: restframework_simplejwt 。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接