如何将授权标头添加到 Angular http 请求?

Posted

技术标签:

【中文标题】如何将授权标头添加到 Angular http 请求?【英文标题】:How to add Authorization Header to Angular http request? 【发布时间】:2018-05-04 04:45:46 【问题描述】:

这是我的第一篇文章。

我刚刚开始学习 Go 和 Angular,我正在尝试将 Angular 应用程序连接到 Go api。我已经写了两个,并且一直在确定问题的根源。我认为这是一个 CORS 问题,但如果我不在我的 Angular http 请求中包含标头代码行,它就可以正常工作。在这一点上,我只是想添加标题。授权码尚未实现。

这两个应用都在本地运行,Go 应用在端口 5000 上,Angular 在 4200 上

Angular http 请求不起作用:

this.http.get<ProjectedBalance>(requestUrl, headers: new HttpHeaders().set('Authorization', 'my-auth-token'))
    .subscribe(data => 
     this.projBalance = data.projBalance;
   

有效的 Angular http 请求:

this.http.get<ProjectedBalance>(requestUrl)
    .subscribe(data => 
     this.projBalance = data.projBalance;
   

我收到此错误:

对预检请求的响应未通过访问控制检查:否 请求中存在“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“http://localhost:4200” 使用权。响应的 HTTP 状态代码为 403

我在我的 go 代码中使用了 gorilla/mux 和 gorilla/handlers

router := mux.NewRouter()
router.HandleFunc("/home/endDate", GetProjBalance).Methods("GET", "OPTIONS")
headersOk := handlers.AllowedHeaders([]string"X-Requested-With, Content-Type, Authorization")
originsOk := handlers.AllowedOrigins([]string"*")
methodsOk := handlers.AllowedMethods([]string"GET", "HEAD", "POST", "PUT", "OPTIONS")
//start server on port
log.Fatal(http.ListenAndServe(":5000", handlers.CORS(originsOk, headersOk, methodsOk)(router)))

Chrome 开发工具的标头

Request URL:http://localhost:5000/home/2020-12-21
Request Method:OPTIONS
Status Code:403 Forbidden
Remote Address:[::1]:5000
Referrer Policy:no-referrer-when-downgrade

Response Headers
view source
Content-Length:0
Content-Type:text/plain; charset=utf-8
Date:Mon, 20 Nov 2017 21:39:43 GMT

Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.9,uz;q=0.8
Access-Control-Request-Headers:authorization
Access-Control-Request-Method:GET
Connection:keep-alive
Host:localhost:5000
Origin:http://localhost:4200

【问题讨论】:

考虑以问题的形式重新表述您的帖子... 我不确定为什么 handlers.CORS 不起作用,但如果您不使用 CORS,则需要将您的开发请求代理到端口 5000。在生产中,您将运行在端口 80 上所以没有冲突,但是由于您使用 angular 的开发服务器并在本地运行您的 go 服务器,localhost:4200localhost:5000 是不同的来源。我不确定执行此操作的“角度 5 方式”是什么,但 webpack-dev-serverpackage.json 中有一个超简单的 proxy 字段,您基本上想复制它。 您好 gobuckeyes,您能否向我提供您的客户端在其向 API 的请求中发送的标头列表(来自开发工具中的网络选项卡)。如果将所有 3 个 CORS 设置为 "*",问题是否仍然存在? @Mihailo 我发布了来自开发工具的标题。将所有三个 CORS 更改为 "*" 将错误更改为 405 - Method not allowed。谢谢 尝试将AllowedMethods() 变回原来的样子。您的客户端应该发送 2 个请求,一个具有 OPTIONS 方法,另一个应该是 GET(针对此特定请求)。还原 AllowedMethods 后,尝试再次发送请求,如果错误仍然存​​在,请使用来自 GET 请求的数据更新问题。 【参考方案1】:

以下示例适合您只希望在访问需要授权的资源时添加一些标头的情况,请参见下面的代码。请注意,您需要在 authentication.service.ts 中创建 getToken 方法。

import  Injectable  from '@angular/core';
import 
  HttpInterceptor,
  HttpRequest,
  HttpHandler,
  HttpEvent
 from '@angular/common/http';
import  Observable  from 'rxjs';

import  environment  from '../../environments/environment';
import  AuthenticationService  from '../services/authentication.service';

@Injectable(
  providedIn: 'root'
)
export class AuthenticationInterceptorService implements HttpInterceptor 
  constructor(public authenticationService: AuthenticationService) 
  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> 
    const accessToken: string = this.authenticationService.getToken();
    // set global application headers.
    request = request.clone(
      setHeaders: 
        'Content-Type': 'application/json; charset=utf-8',
        Accept: 'application/json',
        'X-AppName': environment.xAppName,
        'X-Locale': 'en'
      
    );
    // Set headers for requests that require authorization.
    if (accessToken) 
      const authenticatedRequest = request.clone(
        headers: request.headers.set(
          'Authorization',
          `Token token=$accessToken`
        )
      );
      // Request with authorization headers
      return next.handle(authenticatedRequest);
     else 
      // Request without authorization header
      return next.handle(request);
    
  

app.module.ts中注册拦截器,如下图:

import  BrowserModule  from '@angular/platform-browser';
import  NgModule  from '@angular/core';

import  AuthenticationInterceptorService  from './services/authentication-interceptor.service';

import  AppRoutingModule  from './app-routing.module';
import  AppComponent  from './app.component';
import  HttpClientModule, HTTP_INTERCEPTORS  from '@angular/common/http';

@NgModule(
  declarations: [AppComponent],
  imports: [BrowserModule, AppRoutingModule, HttpClientModule],
  providers: [
    
      provide: HTTP_INTERCEPTORS,
      useClass: AuthenticationInterceptorService,
      multi: true
    
  ],
  bootstrap: [AppComponent]
)
export class AppModule 

【讨论】:

【参考方案2】:

Angular 6 ==> 带有授权标头的 HTTP Get 请求示例

public IsClientCreditCardExits(companyId: string, token: any) 
    let header = new Headers( 'Authorization': `Bearer $token` );
    const options = new RequestOptions(
       headers: header,
    );
    return this._http.get(this.ApiURL + "api/Subscriptions/IsClientCreditCardExits/" + companyId + "/", options);    

【讨论】:

【参考方案3】:

如果您不想添加拦截器,这对我有用:

var header = 
  headers: new HttpHeaders()
    .set('Authorization',  `Basic $btoa(AuthService.getToken())`)


this.http.get(url, header)

对于承载,

set('Authorization',  `Bearer $AuthService.getToken()`)

【讨论】:

【参考方案4】:

关于在 Angular > 4 中处理身份验证标头的最佳方式,最好使用Http Interceptors 将它们添加到每个请求中,然后使用Guards 进行保护你的路线。

这是我在应用中使用的AuthInterceptor 的完整示例:

auth.interceptor.ts

import  HttpEvent, HttpHandler, HttpInterceptor, HttpRequest  from '@angular/common/http';
import  Injectable  from '@angular/core';

import  Observable  from 'rxjs/Observable';

import  AuthService  from './auth.service';

@Injectable()
export class AuthInterceptor implements HttpInterceptor 
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> 
    req = req.clone(
      setHeaders: 
        'Content-Type' : 'application/json; charset=utf-8',
        'Accept'       : 'application/json',
        'Authorization': `Bearer $AuthService.getToken()`,
      ,
    );

    return next.handle(req);
  

您需要在app.module 中将您的拦截器注册为提供者:

app.module.ts

import  HTTP_INTERCEPTORS, HttpClientModule  from '@angular/common/http';
import  AuthInterceptor  from '../auth/auth.interceptor';

...

imports: [
    HttpClientModule,
    ...
],
providers: [
    
      provide : HTTP_INTERCEPTORS,
      useClass: AuthInterceptor,
      multi   : true,
    ,
    ...
],

...

您可以在post 中进一步了解此方法。


关于 Go 方面,这很可能是您发送的请求标头与标头不匹配的情况CORS 允许。 您应该尝试的第一件事是允许所有这些:

headersOk := handlers.AllowedHeaders([]string"*")
originsOk := handlers.AllowedOrigins([]string"*")
methodsOk := handlers.AllowedMethods([]string"GET", "HEAD", "POST", "PUT", "OPTIONS")

如果问题消失,请尝试将您的 CORS 与您的客户发送的内容一一对应。

【讨论】:

这适用于在 Angular 应用程序中添加标题。谢谢!对于 Go 部分,我能够使用这种方法。 ***.com/questions/22452804/… 整洁!很高兴我能帮上忙 :) 祝你好运!【参考方案5】:

这是一个例子:

this.http
        .get(url, return new RequestOptions(
          headers: new Headers(
            Authorization: `Bearer $authtoken`
          ),
        ))
        .map(res => res.json());

【讨论】:

以上是关于如何将授权标头添加到 Angular http 请求?的主要内容,如果未能解决你的问题,请参考以下文章

添加授权标头时出现CORS错误

AJAX 调用后添加授权标头

了解 JWT 和 HTTP 授权标头? (客户端:Angular,服务器:php)

Angular 2/4 如何将多个标题添加到 http post

Guzzle HTTP - 将授权标头直接添加到请求中

骆驼如何将授权标头添加到休息路线?