在 Angular 6 中将 CORS 标头添加到响应中

Posted

技术标签:

【中文标题】在 Angular 6 中将 CORS 标头添加到响应中【英文标题】:Add CORS header to response in Angular 6 【发布时间】:2019-05-05 14:37:03 【问题描述】:

我正在尝试从 Angular 6 中的后端服务器获取一些数据,以便以我自己的方式对其进行可视化。我已经准备了一个有效的 GET 请求,它可以对我需要的所有数据做出正确的响应,但问题是当它以典型方式使用时,例如在“普通”浏览器中,我收到了 CORS 错误 -标题丢失。那么即使有这个问题,我如何获取数据呢?通常,您必须在服务器端允许它,但这种情况有点不同。我已经安装了一个 Chrome 插件来为每个请求添加标题。有了这个插件,CORS 问题就不复存在了。

所以我的问题是,如何(以及是否)将我的 Angular 代码中的 CORS 标头添加到响应中,这样我就不必使用任何插件,并且该应用程序可以在每个浏览器上运行?

另外,为了防止任何 cmets,我获得的所有数据都是我可以合法访问的,它们是我自己的,我只是在 Angular 中学习新东西。据我所知,我应该使用拦截器,但我很确定我做错了。这是我的代码:

http服务方式:

  getFullResponse(domain: string, projectName: string, credentials: Credentials) 
    console.log('RequestService method getIssuesForProject() fired');

    return this.http.get('https://' + domain + '.myserver.local/api/' + projectName,
      
        headers: new HttpHeaders('Authorization': 'Basic ' + btoa(credentials.username + ':' + credentials.password)),
        observe: 'response'
      
    );
  

我写的拦截器类:

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

@Injectable()
export class ResponseInterceptor implements HttpInterceptor 

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> 
    return next.handle(req).pipe(
      map(event => 
        if (event instanceof HttpResponse) 
          event = event.clone(
            headers: event.headers.set('Access-Control-Allow-Origin', '*')
          );
        
        return event;
      )
    );
  


这是 component.ts 类:

import Component, OnInit from '@angular/core';
import RequestService from '../../shared/service/RequestService.service';
import Credentials from '../../shared/model/credentials';

@Component(
  selector: 'app-project',
  templateUrl: './project.component.html',
  styleUrls: ['./project.component.css']
)
export class ProjectComponent implements OnInit 

  projectKey = '';
  headers;
  credentials: Credentials;

  constructor(private reqService: RequestService) 
  

  ngOnInit() 
  

  onSubmit(domainName: string, projectKey: string, user: string, password: string) 
    this.projectKey = projectKey;
    this.credentials = 
      username: user,
      password: password
    ;
    this.reqService.getFullResponse(domainName, projectKey, this.credentials)
      .subscribe(resp => 
        const keys = resp.headers.keys();
        this.headers = keys.map(key => `$key: $resp.headers.get(key)`);
      );
  


我尝试使用 app.module.ts 以 link 下的方式使用拦截器。这完全破坏了我的应用程序,因为即使打开了 CORS 插件,我也会收到 CORS 错误。我在互联网上找到的其他代码示例使用了类似

的代码
return next.handle(reqClone) 
       .map(event =>  
         if (event instanceof HttpResponse)  
           event = event.clone( 
             headers: event.headers.set('x-test-res', 'res-test-header') 
           ); 
          
         return event; 
); 

在拦截器中,但我猜它是针对旧版本的 Angular,我不能以这种方式使用 map 方法,所以我尝试在 pipe 中使用它,就像在 @987654322 中使用它一样@。不过,我仍然缺少一些东西。

【问题讨论】:

【参考方案1】:

它不是那样工作的。 Cors 是在服务器端处理的东西。服务器管理员设置这些标头并允许某些域的位置。您应该适当地查看JsonP,或者如果您像您所说的那样控制数据,请查看允许您的域在您的服务器上。这些是Acces Control Allow Headers

【讨论】:

我知道 CORS 是什么以及它是如何工作的,但我想知道我是否可以使用 Angular 实现与 Chrome 插件相同的效果,它仍然允许我通过添加标题来查看数据。 这个类似的帖子可能会有所帮助:***.com/questions/36250615/cors-with-postman 是的。所以目前看来,Angular 无法做到这一点,因为我必须修改 Web 浏览器的行为,而 Web 应用程序无法做到这一点...... @Jack_Russell 浏览器负责限制 Web 应用访问跨域服务器。只有通过安装插件,您才能更改此行为。不允许网络应用程序更改这一点,因为如果可以,那么拥有 CORS 将毫无意义。【参考方案2】:

当您在向服务器发出的跨源 http 请求中包含某些标头(例如 Authorization)时,浏览器通常会发出 OPTIONSpre flight >) 向服务器请求允许的 Access-Control-Allow-Methods 和允许的 Access-Control-Allow-Headers,您的服务器端代码应使用这些响应浏览器实际发出您想要的 http 请求

【讨论】:

【参考方案3】:

您不需要为请求设置标头。为了避免 Angular 中的 CORS 错误,您应该使用 proxy pass 配置进行开发。

package.json 附近添加一个名为 proxy.conf.json 的文件。从您的请求获取 URL 添加 /proxy

 this.http.get('/proxy/api/' + 
  projectName).subscribe(resData => 
        console.log(resData);
  );

proxy.conf.json中设置代理规则为


  "/proxy/*": 
  "target": "http://backendDomain:8080",
  "secure": false,
  "logLevel": "debug",
  "changeOrigin": true,
  "pathRewrite": 
  "^/proxy": "/"
  
 

只需稍加修改即可更改服务命令:

ng serve --proxy-config proxy.conf.json --port 55055 --host 0.0.0.0

现在对后端的请求将来自相同的角度域,不会再有 CORS 错误

注意:此代理配置仅用于开发目的。对于生产环境你应该在 webservers 中配置。

【讨论】:

问题是,REST API 所在的地址是远程的。我也尝试通过 nginx 代理请求,但我对此完全陌生。由于邮递员请求有效,我想知道是否有办法从我的应用程序发送请求,就好像它是邮递员请求一样,但是这里有些东西不正确,现在我完全迷路了

以上是关于在 Angular 6 中将 CORS 标头添加到响应中的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular 5 的标头中添加 CORS 请求

如何将 CORS 标头添加到 401/403 响应?

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

在 OWIN 中将 CORS 添加到 UseFileServer

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

CORS 多个标头