即使在发送 CORS 标头后从浏览器发送请求到播放服务器时也出现 CORS 错误

Posted

技术标签:

【中文标题】即使在发送 CORS 标头后从浏览器发送请求到播放服务器时也出现 CORS 错误【英文标题】:CORS error while sending request from Browser to play server even after sending CORS header 【发布时间】:2018-09-10 14:35:21 【问题描述】:

我有一个使用 Play Framework/Java 开发的 REST API 和使用 Angular JS 开发的前端。

我正在尝试使用以下代码从 Angular 客户端向服务器调用 POST 方法:

$scope.login = function () 
console.log('login called');
var loginURL = 'http://localhost:9000/login';
var loginInfo = 
    'email': $scope.email,
    'password': $scope.password
;

$http(
    url: loginURL,
    method: 'POST',
    data: loginInfo,
    headers:  'Content-Type': 'application/json' 
).then(function (response) 
    console.log('SUCCESS: ' + JSON.stringify(response));
    $scope.greeting = response.status;
, function (response) 
    console.log('ERROR: ' + JSON.stringify(response));
);

这是我服务器上的代码:

public Result doLogin() 
    ObjectNode result = Json.newObject();
    result.put("status", "success");
    return ok(result).withHeader("Access-Control-Allow-Origin", "*");

这是应用程序配置文件:

#allow all hosts.
play.filter.hosts 
    allowed = ["."]


#allow CORS requests.
play.filters.cors 
  allowedOrigins = ["*"]

即使在启用 CORS 之后,我在 Firefox 和 Google Chrome 的控制台中都出现错误:

跨域请求被阻止:同源策略不允许读取位于http://localhost:9000/login 的远程资源。 (原因:CORS 标头“Access-Control-Allow-Origin”缺失)。 错误:"data":null,"status":-1,"config":"method":"POST","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":" callback","url":"http://localhost:9000/login","data":"email":"xxx","password":"xxx","headers":"Content-Type":"application/json ","Accept":"application/json, text/plain, /","statusText":""

我确实知道服务器正在发送正确的响应和正确的标头,因为当我从 Postman 执行 POST 时,我可以看到响应以及包含 "Access-Control-Allow-Origin", "* " 在邮递员中。

那么,可能是什么问题?客户端有什么我遗漏的吗?

【问题讨论】:

【参考方案1】:

POSTMAN 请求和浏览器请求的区别在于浏览器在实际的 POST / GET 请求之前发送了一个 OPTIONS 请求。

为了能够使用您的播放框架接受 OPTION 请求 allowedHttpMethods = ["GET", "POST" ,"OPTIONS"] 按照这个链接 Play Framework 2.3 - CORS Headers

这会导致从框架(如 angularjs)访问 CORS 请求时出现问题。找到请求的选项并正确采取行动变得困难或框架。

为了解决您的问题,您需要分析选项请求的运行方式以及它是如何被解释的以及如何克服。但总的来说,我建议对此使用“fetch”内置请求,它支持承诺,因此可以轻松地与 angularjs 代码链接

所以你的代码看起来像这样

    $scope.login = function () 
  console.log('login called');
  var loginURL = 'http://localhost:9000/login';
  var loginInfo = 
      'email': $scope.email,
      'password': $scope.password
  ;
fetch(loginURL, 
  method: 'post',
  headers: 
      "Content-type": "application/json"
  ,
  body: loginInfo
).then(function (response) 
  console.log('SUCCESS: ' + JSON.stringify(response));
  $scope.greeting = response.status;
, function (response) 
  console.log('ERROR: ' + JSON.stringify(response));
);

【讨论】:

感谢您的回答,我尝试过这种方式,但仍然出现同样的错误。 您是否在“网络”选项卡中看到发布请求之前的选项请求? $http 请求和 fetch 请求的响应是什么? 实际上在网络选项卡中,我只看到 OPTIONS 请求,在这两种情况下(获取和 http)都没有看到其他请求,唯一的区别是在获取的情况下,原因是“获取”,如果http,原因是'xhr'。两者的状态都是 404。 如果您得到 404 状态,这意味着您根本没有在服务器端包含选项请求处理程序。您还必须在服务器端添加一个选项请求处理程序。您尚未将该部分包含在 sn-p 中。您可以谷歌如何在 playframework 中添加选项请求

以上是关于即使在发送 CORS 标头后从浏览器发送请求到播放服务器时也出现 CORS 错误的主要内容,如果未能解决你的问题,请参考以下文章

带有自定义标头的 Ajax 请求发送到启用 CORS 的 Web API 服务器

如何在 CORS 预检 OPTIONS 请求中发送自定义标头?

来自 IE 或 Firefox 的 CORS 请求中没有 Referer 标头

Axios 未在请求中发送自定义标头(可能是 CORS 问题)

仅在发送标头时出现 Cors

Ionic 2 / Angular 2 / CORS:HTTP 标头未随请求一起发送