Python中文网

一个关于 编程问题的解答网站.

有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

jquery为什么我的JavaScript代码收到“No'AccessControlAllowOrigin'头出现在请求的资源上”错误,而Postman没有?

Mod note: This question is about why XMLHttpRequest/fetch/etc. on the browser are subject to the Same Access Policy restrictions (you get errors mentioning CORB or CORS) while Postman is not. This question is not about how to fix a "No 'Access-Control-Allow-Origin'..." error. It's about why they happen.

Please stop posting:

  • CORS configurations for every language/framework under the sun. Instead find your relevant language/framework's question.
  • 3rd party services that allow a request to circumvent CORS
  • Command line options for turning off CORS for various browsers

我试图通过连接到内置的RESTful{a3}{a4}来使用JavaScript进行授权。但是,当我发出请求时,我得到以下错误:

XMLHttpRequest cannot load http://myApiUrl/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

我知道API或远程资源必须设置头,但是当我通过Chrome扩展Postman发出请求时,为什么它能工作呢

这是请求代码:

$.ajax({
    type: "POST",
    dataType: 'text',
    url: api,
    username: 'user',
    password: 'pass',
    crossDomain : true,
    xhrFields: {
        withCredentials: true
    }
})
    .done(function( data ) {
        console.log("done");
    })
    .fail( function(xhr, textStatus, errorThrown) {
        alert(xhr.responseText);
        alert(textStatus);
    });

共 (6) 个答案

  1. # 1 楼答案

    因为
    $。ajax({type:“POST”-调用选项
    $。post(-调用post

    两者都不同。邮递员恰当地称呼“POST”,但当我们称呼它时,它将是“选项”

    对于C#web服务-Web API

    请在网站中添加以下代码。在<;下配置文件;系统网络服务器>;标签这将有助于:

    <httpProtocol>
        <customHeaders>
            <add name="Access-Control-Allow-Origin" value="*" />
        </customHeaders>
    </httpProtocol>
    

    请确保在Ajax调用中没有犯任何错误

    jQuery

    $.ajax({
        url: 'http://mysite.microsoft.sample.xyz.com/api/mycall',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        type: "POST", /* or type:"GET" or type:"PUT" */
        dataType: "json",
        data: {
        },
        success: function (result) {
            console.log(result);
        },
        error: function () {
            console.log("error");
        }
    });
    

    注意:如果您正在寻找从第三方网站下载内容,则这对您没有帮助。您可以尝试以下代码,但不能尝试JavaScript

    System.Net.WebClient wc = new System.Net.WebClient();
    string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");
    
  2. # 2 楼答案

    如果我理解正确的话,您正在对一个不同的域执行XMLHttpRequest,而不是您的页面所在的域。因此,浏览器正在阻止它,因为出于安全原因,它通常允许同一来源的请求。当您想要执行跨域请求时,您需要执行一些不同的操作。关于如何实现这一点的教程是Using CORS

    当您使用邮递员时,他们不受本政策的限制。引自Cross-Origin XMLHttpRequest

    Regular web pages can use the XMLHttpRequest object to send and receive data from remote servers, but they're limited by the same origin policy. Extensions aren't so limited. An extension can talk to remote servers outside of its origin, as long as it first requests cross-origin permissions.

  3. # 3 楼答案

    应用CORS限制是由服务器定义并由浏览器实施的安全功能

    The browser looks at the CORS policy of the server and respects it.

    但是,Postman工具并不关心服务器的CORS策略

    这就是为什么CORS错误会出现在浏览器中,而不会出现在Postman中

  4. # 4 楼答案

    在下面作为API的调查中,我使用了http://example.com而不是您问题中的http://myApiUrl/login,因为第一个有效

    我假设您的页面位于http://my-site.local:8088.

    您看到不同结果的原因是邮递员:

    • 设置头Host=example.com(您的API)
    • 未设置头Origin

    这类似于浏览器在站点和API具有相同域时发送请求的方式(浏览器也设置了头项Referer=http://my-site.local:8088,但我在Postman中没有看到)Origin未设置时,通常默认情况下服务器允许此类请求

    Enter image description here

    这是邮递员发送请求的标准方式。但是当您的站点和API具有不同的域时,浏览器会以不同的方式发送请求,然后发生CORS,浏览器会自动:

    • 设置头Host=example.com(您的作为API)
    • 设置标题Origin=http://my-site.local:8088(您的站点)

    (头Referer的值与Origin的值相同)。现在在Chrome的控制台&;网络选项卡您将看到:

    Enter image description here

    Enter image description here

    当您有Host != Origin时,这是CORS,当服务器检测到这样的请求时,通常默认情况下会阻止它

    Origin=null是在从本地目录打开HTML内容时设置的,它会发送一个请求。同样的情况是,当您在<iframe>内发送请求时,如下面的代码段中所示(但这里根本没有设置Host头)-一般来说,只要HTML规范说源代码不透明,您就可以将其转换为Origin=null。关于这方面的更多信息,您可以找到here

    &13; 第13部分,;
    fetch('http://example.com/api', {method: 'POST'});
    Look on chrome-console > network tab
    和#13;
    和#13;

    如果您不使用简单的CORS请求,通常浏览器在发送主请求之前也会自动发送一个选项请求-详细信息如下here。下面的代码片段显示了这一点:

    &13; 第13部分,;
    fetch('http://example.com/api', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json'}
    });
    Look in chrome-console -> network tab to 'api' request.
    This is the OPTIONS request (the server does not allow sending a POST request)
    和#13;
和#13;

您可以更改服务器的配置以允许CORS请求

下面是一个示例配置,它在nginx上打开CORS(nginx.conf文件)-在为nginx设置always/"$http_origin"和为Apache设置"*"时要非常小心-这将从任何域取消阻止CORS

&13; 第13部分,;
location ~ ^/index\.php(/|$) {
   ...
    add_header 'Access-Control-Allow-Origin' "$http_origin" always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    if ($request_method = OPTIONS) {
        add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        return 204;
    }
}
和#13;
和#13;

下面是一个在Apache上打开CORS的示例配置(.htaccess文件)

&13; 第13部分,;
# ------------------------------------------------------------------------------
# | Cross-domain Ajax requests                                                 |
# ------------------------------------------------------------------------------

# Enable cross-origin Ajax requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/

# <IfModule mod_headers.c>
#    Header set Access-Control-Allow-Origin "*"
# </IfModule>

# Header set Header set Access-Control-Allow-Origin "*"
# Header always set Access-Control-Allow-Credentials "true"

Access-Control-Allow-Origin "http://your-page.com:80"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"
和#13;
和#13;
  • # 5 楼答案

    WARNING: Using Access-Control-Allow-Origin: * can make your API/website vulnerable to cross-site request forgery (CSRF) attacks. Make certain you understand the risks before using this code.

    如果您使用PHP,那么解决这个问题非常简单。只需在处理请求的PHP页面的开头添加以下脚本:

    <?php header('Access-Control-Allow-Origin: *'); ?>
    

    如果使用Node-red,则必须通过取消注释以下行,在node-red/settings.js文件中允许CORS

    // The following property can be used to configure cross-origin resource sharing
    // in the HTTP nodes.
    // See https://github.com/troygoode/node-cors#configuration-options for
    // details on its contents. The following is a basic permissive set of options:
    httpNodeCors: {
     origin: "*",
     methods: "GET,PUT,POST,DELETE"
    },
    

    如果您使用的是与问题相同的Flask;您必须首先安装flask-cors

    $ pip install -U flask-cors
    

    然后将烧瓶COR包括在您的应用程序中

    from flask_cors import CORS
    

    一个简单的应用程序如下所示:

    from flask import Flask
    from flask_cors import CORS
    
    app = Flask(__name__)
    CORS(app)
    
    @app.route("/")
    def helloWorld():
      return "Hello, cross-origin-world!"
    

    有关更多详细信息,请查看Flask documentation

  • # 6 楼答案

    出现错误的原因是CORS标准,该标准对JavaScript如何执行ajax请求设置了一些限制

    CORS标准是在浏览器中实现的客户端标准。因此,阻止呼叫完成并生成错误消息的是浏览器,而不是服务器

    Postman没有实现CORS限制,这就是为什么当从Postman发出相同的呼叫时,您不会看到相同的错误

    为什么邮递员不实施CORS?CORS定义了与发起请求的页面的来源(URL域)相关的限制。但在Postman中,请求并不来自带有URL的页面,因此CORS不适用