如何解决错误:“对预检请求的响应未通过访问控制检查”

时间:2018-09-27 11:05:34

标签: javascript angular typescript

我正在制作一个使用Spotify API在歌手姓名后进行搜索的应用,但出现此错误:对预检请求的响应未通过访问控制检查:没有“ Access-Control-Allow-Origin”标头存在于请求的资源上。因此,不允许访问来源“ http://localhost:4200”。

spotify.service.ts

import { Injectable } from '@angular/core';
import { Http, Headers, Response } from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class SpotifyService {
  private searchUrl: string;
  
    private client_id ='****************************';
    private client_secret = '*********************************';
    private access_token:string;
    private encoded = btoa(this.client_id + ':' + this.client_secret);

  constructor(private http: Http) { }

  getToken(){
     var params = ('grant_type=client_credentials');

     var headers = new Headers();

     headers.append( 'Authorization', 'Basic ' + this.encoded);
     headers.append('Content-Type' , 'application/x-www-form-urlencoded');

     return this.http.post('https://accounts.spotify.com/api/token', params , {headers : headers} )
     .map(res=> res.json());
  }


  searchMusic(str: string, type='artist', token: string) {
    console.log(this.encoded);
    this.searchUrl = 'https://api.spotify.com/v1/search?query='+str+'&offset=0&limit=20&type='+type;
    let headers = new Headers();
    headers.append('Authorization', 'Bearer' + token);

    return this.http.get(this.searchUrl, {headers: headers})
    .map((res: Response) => res.json())
  }

}

我想在search.component.html中显示结果。这是search.component.ts

import { Component, OnInit } from '@angular/core';
import { SpotifyService } from '../spotify.service';
import { Artist } from '../../../Artist';


@Component({
  selector: 'app-search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.css']
})
export class SearchComponent implements OnInit {
  searchStr: string;
  searchRes: Artist[];

  constructor(private spotifyService: SpotifyService) { }

  ngOnInit() {
  }

  searchMusic() {
    this.spotifyService.getToken()
    .subscribe(res => {
      this.spotifyService.searchMusic(this.searchStr, 'artist', res.access_token)
    .subscribe(res => {
      this.searchRes = res.articles.items;
    })
    })
    
  }

}

我也尝试使用此proxyUrl:

getToken(){
     var params = ('grant_type=client_credentials');

     const proxyUrl = "https://cors-anywhere.herokuapp.com/";

     var headers = new Headers();

     
     headers.append( 'Authorization', 'Basic ' + this.encoded);
     headers.append('Content-Type' , 'application/x-www-form-urlencoded');

     return this.http.post(proxyUrl + 'https://accounts.spotify.com/api/token', params , {headers : headers} )
     .map(res=> res.json());
  }

但是我现在收到此错误:“仅支持有效的承载身份验证”。

P.S。我不想绕过CORS或安装任何扩展程序!

2 个答案:

答案 0 :(得分:0)

安装此chrome扩展程序,它将使您绕过CORS。在本地主机中使用API​​时,我经常使用它。 Chrome CORS extention

答案 1 :(得分:0)

https://accounts.spotify.com/api/token

该斑点端点应该在后端使用。这就是为什么您有一个client_secret令牌的原因。您使用这些凭据在后端发出请求,并获取令牌。然后,您将该令牌发送到前端。

然后在前端,将该令牌用于其他端点,例如https://api.spotify.com/v1/,这些端点的CORS标头设置为允许跨域请求。

例如:

var authToken = null;
fetch('http://yourserver.com/requestNewToken').then(token=>{
  authToken = token;
  //now use that token with your frontend requests like:
  searchMusic(this.searchStr, 'artist', authToken)
});

http://yourserver.com/requestNewToken是您在服务器上创建的某个终结点,将在其中调用https://accounts.spotify.com/api/token并返回令牌响应。

旁注,因为您的client_secret现在已经被盗用,您应该重新制作一个。

还要确保从整体上通读Spotify的开发人员帮助页面,例如Client Credentials FlowAuthorization page,以便更好地理解提出请求的正确流程模式。