Angular 2 http 标头似乎生成或发送不正确

Posted

技术标签:

【中文标题】Angular 2 http 标头似乎生成或发送不正确【英文标题】:Angular 2 http header seems to be generated or send incorrectly 【发布时间】:2016-08-02 05:45:05 【问题描述】:

我正在尝试向使用 HTTP Basic auth 进行身份验证的后端发送请求。 用于测试目的

username: user
password: password

所以正确的标题是:

Authorization: Basic dXNlcjpwYXNzd29yZA==

我已经在 Chrome Advanced Rest Extension 中测试了带有此标头的请求,并且可以正常工作:

我在 Angular2 中生成了这样的请求:

  public getCurrentCounter() 
    console.log("Method getCurrentCounter() in CounterService called");

    var request = this.backendURL + "counter";
    var header = this.generateHeader(this.username, this.password);
    console.log(header);

    return this._http.get(request, 
      headers: header
    )
      .map(res => res.json());
  

  /**
   * Generate HTTP header using HTTP basic Auth
   */
  private generateHeader(username, password) 

    var base64Creds = btoa(username + ":" + password);
    var auth = 'Basic ' + base64Creds;
    console.log(auth);
    var authHeader = new Headers();
    authHeader.append("Authorization", auth);

    return authHeader;
  

我记录了生成的 Header Object,它看起来像这样:

我仍然收到此回复:

XMLHttpRequest cannot load http://localhost:8080/counter. Response for preflight has invalid HTTP status code 401

有人知道可能是什么问题吗?

【问题讨论】:

网络服务器是否在您的应用程序的同一端口上运行? 不,后端在 8080,前端 8081 好吧,我在想,然后就是 CORS 【参考方案1】:

问题与服务器端未启用的CORS有关。

您的服务必须使用以下标头回答 OPTIONS 请求:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: [the same ACCESS-CONTROL-REQUEST-HEADERS from request]

这是一个很好的文档:http://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server

也看看这个:Chrome v37/38 CORS failing (again) with 401 for OPTIONS pre-flight requests

对于 angularjs 1.x 中的基本身份验证,请您尝试一下:

service.SetCredentials = function (username, password) 
    var authdata = Base64.encode(username + ':' + password);
    $http.defaults.headers.common = "Access-Control-Request-Headers": "accept, origin, authorization"; //you probably don't need this line.  This lets me connect to my server on a different domain
    $http.defaults.headers.common['Authorization'] = 'Basic ' + authdata; // jshint ignore:line

        ;

Angularjs 2.x 版本请查看:

Angular2 - set headers for every request

我发现扩展 BaseRequestOptions 非常有趣:

class MyRequestOptions extends BaseRequestOptions 
  constructor () 
    super();
    this.headers.append('Authorization', 'Basic ' + authdata);
  
 

希望对你有帮助

【讨论】:

感谢您的回答,遗憾的是没有解决问题。此外,如果这将是一个 CORS 问题,则会有 403 响应而不是 401 401 Unauthorized 是身份验证错误的 HTTP 状态代码。您的服务器是否支持基本身份验证? 是的,基本身份验证的标头似乎没有正确设置,这里的问题 $http.defaults.headers.common['Authorization'] = 'Basic' + authdata 是诀窍 $http 是什么意思? http 对象没有defaults 字段。【参考方案2】:

原来问题出在后端。

后端希望OPTIONS 请求也经过基本身份验证,但由于从 angular2 发送的OPTIONS 请求没有身份验证标头,我们得到了 401 响应。

限制需要在后端进行身份验证的请求类型解决了这个问题。

【讨论】:

将 Angular 2 RTM 与 ASP.NET Core (full fx) 结合使用,在调用安全 api 时,我必须将以下内容添加到我的 API(服务器)中:public static class CorsBuilder public static IApplicationBuilder UseCors(this IApplicationBuilder app) app.UseCors(x => x.AllowAnyHeader() .AllowAnyMethod() .AllowAnyOrigin() .AllowCredentials(); ); return app; 【参考方案3】:

要么您忘记导入Headers 类。您需要在请求的基础 XHR 上将 withCredentials 属性设置为 true

为此,您可以执行以下操作。先扩展BrowserXhr

@Injectable()
export class CustomBrowserXhr extends BrowserXhr 
  constructor() 
  build(): any 
    let xhr = super.build();
    xhr.withCredentials = true;
    return <any>(xhr);
  

并使用扩展类覆盖BrowserXhr 提供程序:

bootstrap(AppComponent, [
  HTTP_PROVIDERS,
  provide(BrowserXhr,  useClass: CustomBrowserXhr )
]);

【讨论】:

试过了,遗憾的是问题仍然存在【参考方案4】:

您能否验证一下,但您似乎从 OPTIONS 请求中收到此错误?而不是 GET 请求。

【讨论】:

服务器以某种方式返回 401 以获取奇怪的选项请求。你用什么框架? 你的意思是在后端吗? 是的,在后端很抱歉 Spring Boot,但正如我所说,当在浏览器或 chrome rest 扩展中执行请求时,它会正常工作。 是的,但在 chrome rest 扩展中,它可能不是 ajax 请求,因此没有 OPTIONS 预检请求。尝试使用 chrome rest 扩展和 OPTIONS http 方法调用 api,您应该能够重现问题

以上是关于Angular 2 http 标头似乎生成或发送不正确的主要内容,如果未能解决你的问题,请参考以下文章

Angular2 - HTTP RequestOptions 标头

我无法在 Angular 4 上向 laravel api 发送带有标头的 http 请求

如何防止 angular.js $http 对象发送 X-Requested-With 标头?

Angular $http 未在 OPTIONS 飞行前发送标头

使用 OPTIONS 方法未使用 http 请求 Angular 6 发送授权标头

如何在Angular js中的http请求中发送标头数据