Magento 2 Token Auth - 400错误/ CORS问题

时间:2016-07-13 10:05:01

标签: jquery ajax magento cors

我在我的应用中使用令牌身份验证来访问magento API。我在postman中进行以下设置,它运行正常: enter image description here

然而,使用jQuery帖子我一直得到400错误,因为它似乎不支持预检的HTTP动词OPTIONS(我有nginx的CORS配置)。我试过了:

$.ajax({
  method: "POST",
  url: `myip/index.php/rest/V1/integration/admin/token`,
  data: {username: 'ember-app', password: 'ember-app2'},
}).done(function(response) {
  alert(response);
});

$.ajax({
  method: "POST",
  url: `myip/index.php/rest/V1/integration/admin/token?username=ember-app&password=ember-app2`
}).done(function(response) {
  alert(response);
});

$.post(
  'myip/index.php/rest/V1/integration/admin/token', 
  {username: 'ember-app', password: 'ember-app2'},
  function(response) { alert(response); }
);

我还在对象周围尝试过JSON.stringify。为什么它在邮递员中工作但在xhr我经常得到400错误?此外,该请求然后触发另一个GET请求,返回一个cors错误。一些我的$ .post会在控制台中导致这种情况:

enter image description here

以下是一些cURL回复:

curl -H "Origin: http://localhost:4200" \
  -H "Access-Control-Request-Method: POST" \
  -H "Access-Control-Request-Headers: X-Requested-With" \
  -d '{"username": "ember-app", "password": "ember-app2"}'\
  -X OPTIONS --verbose https://myhost/index.php/rest/V1/integration/admin/token

给出的答案是:

{"message":"Request method is invalid."} 

同样:

curl -H "Origin: http://localhost:4200" \
  -H "Access-Control-Request-Method: POST" \
  -H "Access-Control-Request-Headers: X-Requested-With" \
  -X OPTIONS --verbose https://myhost/index.php/rest/V1/integration/admin/token?username=ember-app&password=ember-app2

然而,正常的卷曲工作正常:

curl -H "Content-Type: application/json" -X POST -d '{"username":"ember-app","password":"ember-app2"}' https://myhos/index.php/rest/V1/integration/admin/token

3 个答案:

答案 0 :(得分:5)

当请求来自与服务第一资源的域不同的域请求资源时,将该请求标识为跨源HTTP请求。出于安全原因,在脚本中发起的跨源HTTP请求在浏览器中受到限制。

W3C的跨域资源共享(CORS)机制定义了一种标准,该标准为Web服务器提供跨域访问控制,以实现安全的跨域数据传输。它的工作原理是添加新的HTTP标头,允许服务器使用Web浏览器定义允许访问该信息的起源集。

此外,一些HTTP请求在修改用户数据时默认为非安全。这些请求在Web浏览器中自动预检。这意味着在发送请求之前,浏览器会将带有OPTIONS谓词的预检请求发送到其他域服务器,以确定实际请求是否可安全发送或不。经服务器批准后,将发送实际请求。

当您使用邮递员时,您的实际请求会被发送。没有CORS保护或任何东西,Postman不是一个Web浏览器。它只是有效。

当您使用jQuery在Web浏览器的脚本中进行AJAX调用时,它将遵循CORS标准并标记您的请求是不安全的,这意味着它应该预检< / em>的。然后,它会使用OPTIONS方法向您的服务器发送第一个请求,以检查您的实际请求是否安全。需要在您的Web服务器(似乎是Nginx)上允许这些请求。

您可以查看this example如何在Nginx上启用CORS,并将其与您的实际配置进行比较。一个基本的开放式配置(我添加了一些评论):

location / {
  // OPTIONS requests.
  if ($request_method = 'OPTIONS') {
    // URI that may access the resource.
    add_header 'Access-Control-Allow-Origin' '*';

    // Methods allowed when accessing the resource.
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';

    // Headers that can be used when making the actual request.
    add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

    // Cache the preflight result for 20 day.
    add_header 'Access-Control-Max-Age' 1728000;

    add_header 'Content-Type' 'text/plain charset=UTF-8';
    add_header 'Content-Length' 0;

    return 204;
  }

  // POST requests.
  if ($request_method = 'POST') {
    // URI that may access the resource.
    add_header 'Access-Control-Allow-Origin' '*';

    // Methods allowed when accessing the resource.
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';

    // Headers that can be used when making the actual request.
    add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
  }

  // GET requests
  if ($request_method = 'GET') {
    // URI that may access the resource.
    add_header 'Access-Control-Allow-Origin' '*';

    // Methods allowed when accessing the resource.
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';

    // Methods allowed when accessing the resource.
    add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
  }
}

如果服务器端的所有内容都是有序的,那么您应该调整jQuery请求以匹配服务器上预期的内容。

jQuery.ajax({
  url: 'https://host/rest/V1/integration/admin/token',
  data: JSON.stringify({"username": "ember-app", "password": "ember-app2"}),
  contentType: "application/json",
  method: 'POST'
}).done((response) => {
  alert(response);
})

答案 1 :(得分:0)

在这种情况下看起来CORS错误是一个红色的鲱鱼。

您提到用于令牌生成的Magento端点/V1/integration/admin/token

您无需在自己的应用中使用此功能。

相反,这可以是一个多步骤的过程。

  1. 生成令牌 http://devdocs.magento.com/guides/v2.0/get-started/authentication/gs-authentication-token.html#auth-request

  2. 将令牌存储在配置文件中

  3. 对于任何Web API请求,请在Authorization请求标头中使用Bearer HTTP授权方案指定令牌。 http://devdocs.magento.com/guides/v2.0/get-started/authentication/gs-authentication-token.html#web-api-access

答案 2 :(得分:0)

在Magento .htaccess文件中包含以下行,该文件位于Magento的根文件夹中。它对我有用。

Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"

# Added a rewrite to respond with a 200 SUCCESS on every OPTIONS request.
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]