jQuery AJAX 调用导致错误状态 403

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36666256/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 17:06:09  来源:igfitidea点击:

jQuery AJAX call results in error status 403

jqueryajaxcorshttp-status-code-403

提问by Some User

I'm making a query to a web service using jQuery AJAX. My query looks like this:

我正在使用 jQuery AJAX 对 Web 服务进行查询。我的查询如下所示:

var serviceEndpoint = 'http://example.com/object/details?version=1.1';
$.ajax({
  type: 'GET', 
  url: serviceEndpoint,
  dataType: 'jsonp',
  contentType: 'jsonp',
  headers: { 'api-key':'myKey' },
  success: onSuccess,
  error: onFailure
});

When I execute this, I get a status error of 403. I do not understand why my call results in having the status code 403. I'm in control of the security on my service and it is marked as wide-open. I know the key is valid, because I'm using it in another call, which works. Here is the call that works:

执行此操作时,我收到 403 状态错误。我不明白为什么我的调用会导致状态代码为 403。我控制着我的服务的安全性,它被标记为完全开放。我知道密钥是有效的,因为我在另一个调用中使用它,它有效。这是有效的调用:

var endpoint = 'http://example.com/object/data/item?version=1.1';
$.ajax({ 
  type: 'POST', 
  url: endpoint, 
  cache: 'false',
  contentType:'application/json',
  headers: {
    'api-key':'myKey',
    'Content-Type':'application/json'
  },
  data: JSON.stringify({
    id: 5,
    count:true
  }),
  success: onDataSuccess,
  error: onDataFailure
});

I know these are two different endpoints. But I'm 100% convinced this is not a server-side authentication or permission error. Once again, everything is wide open on the server-side. Which implies that I'm making some mistake on my client-side request.

我知道这是两个不同的端点。但我 100% 确信这不是服务器端身份验证或权限错误。再一次,服务器端的一切都是开放的。这意味着我在客户端请求上犯了一些错误。

I feel I should communicate that this request is being made during development. So, I'm running this from http://localhost:3000. For that reason, I immediately assumed it was a CORS issue. But everything looks correct. The fact that my POST request works, but my GET doesn't has me absolutely frustrated. Am I missing something? What could it be?

我觉得我应该传达这个请求是在开发过程中提出的。所以,我从http://localhost:3000运行它。出于这个原因,我立即认为这是 CORS 问题。但一切看起来都是正确的。我的 POST 请求有效,但我的 GET 并没有让我完全沮丧。我错过了什么吗?会是什么呢?

回答by ykaragol

The reason of 403 error is you are not sending headers. Since you are making a CORS request, you cannot send any custom headers unless server enables these header by adding Access-Control-Allow-Headersto the response.

403 错误的原因是您没有发送 headers。由于您正在发出 CORS 请求,因此您无法发送任何自定义标头,除非服务器通过添加Access-Control-Allow-Headers到响应来启用这些标头。

In a preflighted-request, client makes 2 requests to the server. First one is preflight (with OPTIONS method) and the second one is the real request. The server sends Access-Control-Allow-Headersheader as a response of the preflight request. So it enables some headers to be sent. By this way your POST request can work because the POST request is a preflight-request. But for a GET request, there is no preflight to gather Access-Control-Allow-Headersheader and browser doesn't send your custom headers in this case.

preflighted-request 中,客户端向服务器发出 2 个请求。第一个是预检(使用 OPTIONS 方法),第二个是真正的请求。服务器发送Access-Control-Allow-Headers标头作为预检请求的响应。因此它可以发送一些标头。通过这种方式,您的 POST 请求可以工作,因为 POST 请求是一个预检请求。但是对于 GET 请求,没有预检来收集Access-Control-Allow-Headers标头,并且在这种情况下浏览器不会发送您的自定义标头。

A workaround for this issue:

此问题的解决方法:

As a workaround, set your dataTypeand contentTypeto jsonas the following:

作为一种解决方法,将您的dataTypecontentType设置json为如下:

var serviceEndpoint = 'http://example.com/object/details?version=1.1';
$.ajax({
  type: 'GET', 
  url: serviceEndpoint,
  dataType: 'json',
  contentType: 'json',
  headers: { 'api-key':'myKey' },
  success: onSuccess,
  error: onFailure
});

By this way, your get request will be a preflighted request. If your server enables the api-keywith Access-Control-Allow-Headersheader, it will work.

通过这种方式,您的 get 请求将是一个preflighted request. 如果您的服务器启用api-keywith Access-Control-Allow-Headers标头,它将起作用。

Sample server configuration for the above request (written in express.js):

上述请求的示例服务器配置(用 express.js 编写):

res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', '*');
res.setHeader('Access-Control-Allow-Headers', 'api-key,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);

ADDED:

添加:

Actually, contentTypeshould be either application/javascriptor application/jsonwhile doing a jsonp request. There is no contentTypeas jsonp.

实际上,contentType应该是application/javascript或者application/json在执行 jsonp 请求时。没有contentType作为jsonp

回答by Clomp

If you look at the API pagefor jQuery's Ajax call, it mentions the following in the Content-Type section:

如果您查看jQuery 的 Ajax 调用的API 页面,它会在 Content-Type 部分提到以下内容:

Note:For cross-domain requests, setting the content type to anything other than application/x-www-form-urlencoded, multipart/form-data, or text/plain will trigger the browser to send a preflight OPTIONS request to the server.

注意:对于跨域请求,将内容类型设置为 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 以外的任何内容将触发浏览器向服务器发送预检 OPTIONS 请求。

That page doesn't really mention what a "preflight OPTIONS request" is, but I found some interesting links when looking that phrase up online:

该页面并没有真正提到“预检选项请求”是什么,但我在网上查找该短语时发现了一些有趣的链接:

What's intersting is the code example& the CORS imageat the HTML5Rocks page. The image shows how the Ajax calls are being made from the JavaScript code to the browser to the server & how the responses are round-tripping between all 3 of those.

有趣的是 HTML5Rocks 页面上的代码示例CORS 图像。该图显示了 Ajax 调用是如何从 JavaScript 代码到浏览器再到服务器的,以及响应是如何在所有这三者之间来回传递的。

We tend to think of JavaScript + Browser = Client, but in the illustration the author is explaining the difference between the web developer's code & the browser developer's code, where the former is written in JavaScript code, but the latter was written using C, C++ or C# code.

我们倾向于认为 JavaScript + 浏览器 = 客户端,但在插图中作者解释了 Web 开发人员的代码和浏览器开发人员的代码之间的区别,前者是用 JavaScript 代码编写的,而后者是使用 C、C++ 编写的或 C# 代码。

A good packet analyzer tool is Fiddler, which would be similar to Wireshark. Either one of those tools, should show you the pre-flight requests which are being sent from the browser to the server. Most likely, that's where your Ajax request is being blocked at by the server with a 403 Forbidden error.

一个很好的数据包分析工具是Fiddler,它类似于Wireshark。这些工具中的任何一个都应该向您显示从浏览器发送到服务器的飞行前请求。很可能,这就是您的 Ajax 请求被服务器以403 Forbidden error阻止的地方。