Angular 7应用程序从Angular客户端获取CORS错误

21

我已经开发了一个带有Express后端的Angular 7应用程序。 Express运行在localhost:3000上,而Angular客户端则在localhost:4200上运行。

server.js中,我有以下代码(不是完整的代码):

const app = express();
// Enable CORS
app.use(cors());
// Get our API routes
const api = require('./api');
// Set our api routes
app.use('/api', api);
app.use(express.static(__dirname + '/dist/sfdc-event'));

在api.js文件中,我有router.get('/oauth2/login'),它重定向到https://example.com,该网站会发送访问令牌并对用户进行身份验证(OAuth2认证)。
当我调用urlhttp://localhost:3000/api/oauth2/login时,一切都正常工作,但是当我尝试从Angular组件.ts -> service.ts执行相同操作时,我遇到了以下错误。

跨域请求被阻止:同源策略禁止读取远程资源原因:缺少CORS头“Access-Control-Allow-Origin”

Angular应用程序的流程如下:login.component.ts具有调用api.service.ts的按钮,该服务执行http get。
login.component.ts

sfdcLogin(): void {
  console.log('DEBUG: LoginComponent: ', 'Login button clicked..');
 this.apiService.login().subscribe( data => { console.log( data ); });
}

api.service.ts

login() {
  console.log('DEBUG: APiService login(): ', 'login() function.');
  const URL = 'oauth2/login';
  console.log('DEBUG: ApiService login URL : ', `${environment.baseUrl}/${URL}`.toString());
  return this.http.get(`${environment.baseUrl}/${URL}`)
    .pipe( map( res => res ));
}

有人能帮我解决这个错误吗?我遇到了a) CORS b) 在server.js中作为静态文件进行服务。

app.use(express.static(__dirname + '/dist/sfdc-event'));

c) 动态环境变量。 还有什么我遗漏了吗?


响应的HTTP状态码是什么? - sideshowbarker
@Arup Sarkar,如果适用,请标记正确答案。 - Aaron Matthews
9个回答

8
如果只是用于开发,建议使用angular-cli自带的代理工具。 创建一个名为proxy.json的文件。
{
  "/api/oauth2/login": {
    "target": "http://localhost:3000/api/oauth2/login",
    "secure": false
  }
}

需要运行命令ng serve --proxy-config proxy.json。如果您认为这在生产环境中仍然是一个问题,那么我们需要进行更深入的讨论。

完整文档: https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/proxy.md

CORS是什么:https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS


8

对于Angular 7,您必须进行其他实现。从Angular文档中,您必须创建一个proxy.js文件:

https://angular.io/guide/build#using-corporate-proxy

编辑您自己的后端服务器路径。

proxy.js:

var HttpsProxyAgent = require('https-proxy-agent');
var proxyConfig = [{
  context: '/api',
  target: 'http://your-remote-server.com:3000',
  secure: false
}];

function setupForCorporateProxy(proxyConfig) {
  var proxyServer = process.env.http_proxy || process.env.HTTP_PROXY;
  if (proxyServer) {
    var agent = new HttpsProxyAgent(proxyServer);
    console.log('Using corporate proxy server: ' + proxyServer);
    proxyConfig.forEach(function(entry) {
      entry.agent = agent;
    });
  }
  return proxyConfig;
}

module.exports = setupForCorporateProxy(proxyConfig);

稍后将此添加到您的package.json文件中

"start": "ng serve --proxy-config proxy.js"

并使用以下方式调用:

npm start

在你的 app.js 文件中,只需要简单地添加以下内容:
const cors = require("cors");
app.use(cors());

我曾经也遇到过同样的问题,这个方法解决了我的问题。希望可以帮到你!


6
要将所有针对http://localhost:4200/api的调用重定向到运行在http://localhost:3000/api上的服务器,请执行以下步骤
  1. 在项目的src/文件夹中,与package.json旁边创建一个名为proxy.conf.json的文件。

  2. 将以下内容添加到新代理文件中:

{
    "/api": {
        "target": "`http://localhost:3000`",
        "secure": false
    }
}
  1. 在CLI配置文件angular.json中,为serve目标添加proxyConfig选项:
...
"architect": {
    "serve": {
        "builder": "@angular-devkit/build-angular:dev-server",
        "options": {
            "browserTarget": "your-application-name:build",
            "proxyConfig": "src/proxy.conf.json"
        },
    ...
    }
}
...
  1. 要使用此代理配置运行开发服务器,请调用 ng serve

谢谢你的解释。这就是我所做的,但我在使用Angular 9和Express.js时仍然遇到了问题: 访问'localhost:7777/api/login' 的XMLHttpRequest从来源'http://localhost:4200'被CORS策略阻止:跨域请求仅支持协议方案:http、data、chrome、chrome-extension和https。 - phenric
@DineshKumar 我不是这个答案的原始所有者,我只是编辑了它以获得清晰的代码格式,你应该问TiyebM。无论如何,我想是的,但我没有尝试过。 - Ferie
你好,目标已设为"http://localhost:3000"。在QA或PRODUCTION环境中,如何进行设置?我们只有一个代理文件。 - Bigeyes

2
我更改了回调机制以解决跨域问题,我正在利用OAuth流程让用户从https://example.com进行身份验证,该网站将重定向到https://example.com/auth/callback。我在http://localhost:4200上发起请求,然后将回调URL发送到服务器http://localhost:3000,但是我遇到了CORS错误。
现在,我将其重定向到客户端http://localhost:4200并成功解决了CORS问题。所有其他的GET、POST、DELETE、PATCH调用都来自于http://localhost:3000,这部分已经正常运行。
感谢大家的意见。

针对 .NET Core,请查看以下链接:https://www.c-sharpcorner.com/article/enable-cors-consume-web-api-by-mvc-in-net-core-4/ - William

2
我一直在使用Angular cli和.net Framework进行服务器端开发。
要解决这个问题,我只需在服务器端启用CORS交互,按照以下步骤操作:
1. 安装Microsoft.AspNet.WebApi.Cors 5.2.6包。 2. 在WebApiConfig类中添加using System.Web.Http.Cors。 3. 在Register(HttpConfiguration config)方法内部:
var cors = new EnableCorsAttribute("http://localhost:4200", "*", "*");

config.EnableCors(cors);
最初的回答
或者
var cors = new EnableCorsAttribute("*", "*", "*"); //origin, headers, methods

config.EnableCors(cors);

0
默认情况下,Angular设置了一些请求头参数,其中之一是“Content-Type”,其默认值为“application/json”。当我将其设置为“application/x-www-form-urlencoded”时,这为我解决了错误。
而不是使用post方法像这样:
this.http.post<any>(requestDetails['url'],requestDetails['data'])

首先使用Angular的HttpHeaders类设置请求头,例如:

let reqHeaders = new HttpHeaders({
   'Content-Type':'application/x-www-form-urlencoded'
});
this.http.post<any>(requestDetails['url'],requestDetails['data'],{headers:reqHeaders})

参考:https://angular.io/guide/http#adding-and-updating-headers

在我的情况下,服务器的响应头中'Access-Control-Allow-Origin'也被设置为*,以接受来自任何源的请求(在开发案例中通常是:localhost: 4200)


0
所以为什么我们会遇到CORS错误呢?因为我们试图连接两个不同的域,但可能的原因是版本问题。在我的情况下,我使用了Angular代理,并且它完美地工作。 当我们使用Angular代理时,有可能它不起作用,因为你没有完全理解如何正确使用它。

-2

我知道这个问题已经有答案了,但它可能会帮助正在寻找CORS问题解决方案的人。 您可以按照以下3个步骤解决此问题。 1. 创建proxy.conf.json文件并将其放在应用程序的根目录下。 2. 在package.json文件中,在ngstart中添加代理参数 3. 在angular.json中,添加代理文件条目。 4. 将所有rest调用更改为类似于/api/getData的内容。

这里提供了详细的逐步教程。 http://www.codeyourthought.com/angular/proxy-to-make-http-call-in-angular/


-5

由于您的Angular应用程序运行在4200端口,而后端运行在3000端口,因此两个应用程序的来源不同。

为了解决这个问题,您可以在您的机器上设置“nginx”。

这将使您所有来自Angular和后端的请求都通过“nginx”服务器进行。从而解决CORS问题。


最终,这将托管在Heroku PAAS上。我不确定我能否使用“nginx”服务器。顺便说一下,我已经将应用程序上传到Heroku,并且它的行为是相同的。 - Arup Sarkar
1
@ArupSarkar 我相信在Heroku中有CORS头设置。阅读这篇文章只需10分钟,它会解释一切:https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS - piotr szybicki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接