通过 Angular 4 将 JWT 令牌附加到 api 请求

Posted

技术标签:

【中文标题】通过 Angular 4 将 JWT 令牌附加到 api 请求【英文标题】:attach a JWT token to api request via angular 4 【发布时间】:2018-04-09 02:24:42 【问题描述】:

我正在构建一个带有 ASP.NET Core 2.0 后端的 Angular 应用程序。我已经成功实现了 JWT 登录,它工作正常。现在,按照位于here 的教程,我正在尝试获取需要通过 JWT 授权的资源的数据。当我使用令牌获取 HTTP 时,我使用邮递员验证这是否有效。

在我的 Angular 应用程序中,我收到 401。我将 Visual Studio 2017 Angular 模板应用程序用于我的示例应用程序。其他一切正常,我可以登录,当我的令牌过期时,我被要求再次登录,以便所有这些方面都能正常工作。我只是错过了最后一部分。 服务端api调用如下:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Route("api/[controller]")]
public class SampleDataController : Controller

    private static string[] Summaries = new[]
    
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    ;

    [HttpGet("[action]")]
    public IEnumerable<WeatherForecast> WeatherForecasts()
    
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        
            DateFormatted = DateTime.Now.AddDays(index).ToString("d"),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        );
    

    public class WeatherForecast
    
        public string DateFormatted  get; set; 
        public int TemperatureC  get; set; 
        public string Summary  get; set; 

        public int TemperatureF
        
            get
            
                return 32 + (int)(TemperatureC / 0.5556);
            
        
    

角度组件有如下代码:

    import  Component, Inject  from '@angular/core';
import  Http  from '@angular/http';

@Component(
    selector: 'fetchdata',
    templateUrl: './fetchdata.component.html'
)
export class FetchDataComponent 
    public forecasts: WeatherForecast[];

    constructor(http: Http, @Inject('BASE_URL') baseUrl: string) 
        http.get(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => 
            this.forecasts = result.json() as WeatherForecast[];
        , error => console.error(error));
    


interface WeatherForecast 
    dateFormatted: string;
    temperatureC: number;
    temperatureF: number;
    summary: string;

这是添加授权标头的代码:

    import  Injectable  from '@angular/core';

import 
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor from '@angular/common/http';
//import  AuthService  from './auth/auth.service';
import  Observable  from 'rxjs/Observable';
import  Http  from "@angular/http/http";
import  AuthService  from "./auth.service";
import  HttpClient  from "@angular/common/http";
@Injectable()
export class TokenInterceptor implements HttpInterceptor 
  constructor(public auth: AuthService)  
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> 

    request = request.clone(
      setHeaders: 
        Authorization: `Bearer $this.auth.getToken()`
      
    );
    return next.handle(request);
  

我们将不胜感激。

【问题讨论】:

【参考方案1】:

问题出在这里:

   Authorization: `Bearer $this.auth.getToken()`

getToken 方法正在返回整个 Token 对象。相反,正如有人在另一个线程上指出的那样,我必须显式提取实际的令牌字符串,如下所示:

JSON.parse(localStorage.getItem('token')).token

这解决了我的问题。

【讨论】:

【参考方案2】:

您可以将选项参数传递给您的 http get 方法,请查看此处 https://angular.io/api/http/RequestOptionsArgs

【讨论】:

【参考方案3】:

所以这个很简单,你发的教程用的是angualar-jwt(我自己用过)。

他们为 http 服务提供自己的包装器,该服务将保存的 JWT 令牌作为请求的一部分发送到您(或其他人的)API 端点。

如果是其他人的 API,请确保您更改标头前缀以匹配他们期望 JWT 令牌的位置。

来自 angular2-jwt 自述文件:

如果您希望仅针对特定 HTTP 请求发送 JWT,则可以使用 AuthHttp 类。此类是 Angular 2 的 Http 的包装器,因此支持所有相同的 HTTP 方法。

import  AuthHttp  from 'angular2-jwt';
// ...
class App 

thing: string;

constructor(public authHttp: AuthHttp) 

getThing() 
    this.authHttp.get('http://example.com/api/thing')
    .subscribe(
        data => this.thing = data,
        err => console.log(err),
        () => console.log('Request Complete')
    );


【讨论】:

嗨,如果你看一下教程,他们有一个 Ping 组件,它使用新的 HttpClient 类来获取数据。因此,这应该可以在不使用您的方法的情况下工作 我已经更新了拦截器代码的问题。它会自动将任何令牌附加到授权标头,因此不需要额外的工作

以上是关于通过 Angular 4 将 JWT 令牌附加到 api 请求的主要内容,如果未能解决你的问题,请参考以下文章