首页 文章

为什么我的JavaScript在Postman没有时会出现“请求的资源上没有'Access-Control-Allow-Origin'标头”错误?

提问于
浏览
1995

我正在尝试使用JavaScript进行授权,方法是连接到Flask中内置的RESTful API . 但是,当我发出请求时,我收到以下错误:

XMLHttpRequest无法加载http:// myApiUrl / login . 请求的资源上不存在“Access-Control-Allow-Origin”标头 . 因此不允许原点'null'访问 .

我知道API或远程资源必须设置 Headers ,但为什么在我通过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);
    });

30 回答

  • 468

    使用Ajax存在跨域问题 . 您必须确保在相同的 http:// 路径上访问您的文件而没有 www. (或从 http://www. 访问并发布到相同的路径,包括 www. ),当通过 www. 路径访问时,浏览器认为该路径是另一个域,因此您可以看到问题所在是 . 您正在发布到其他域,并且浏览器会因原始问题阻止流 .

    如果API未放置在您请求的同一主机上,则会阻止该流,您需要找到另一种与API通信的方式 .

  • 8

    如果我理解正确,那么您正在使用与您的网页不同的域名.1735905_ . 因此浏览器会阻止它,因为出于安全原因,它通常允许同一来源的请求 . 当您想要执行跨域请求时,您需要做一些不同的事情 . 关于如何实现这一目标的教程是Using CORS .

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

    常规网页可以使用XMLHttpRequest对象从远程服务器发送和接收数据,但它们受到相同原始策略的限制 . 扩展不是那么有限 . 扩展可以与其来源之外的远程服务器通信,只要它首先请求跨源权限即可 .

  • 2

    这不是 生产环境 修复或者必须向客户端显示应用程序时,这仅在UI和后端开发位于不同服务器上并且在 生产环境 中实际位于同一服务器上时才有用 . 例如:在为任何应用程序开发UI时,如果需要在本地测试它指向后端服务器,那么这是一个完美的修复 . 对于 生产环境 修复,必须将CORS头添加到后端服务器以允许跨源访问 .

    简单的方法是在谷歌浏览器中添加扩展名以允许使用CORS进行访问 .

    https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en-US

    只要您希望允许访问没有 'access-control-allow-origin' 标头请求,只需启用此扩展程序 .

    Or

    在Windows中,将此命令粘贴到 run 窗口中

    chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security
    

    这将打开一个新的 chrome 浏览器,允许访问没有 'access-control-allow-origin' 标头请求 .

  • 4

    如果你可以回复JSON,那么尝试使用JSONP(注意结尾的 P )在域名之间说话:

    $.ajax({
      type: "POST",
      dataType: 'jsonp',
      ...... etc ......
    

    了解有关使用JSONP的更多信息here

    JSONP的出现 - 本质上是一个双方同意的跨站点脚本黑客 - 为强大的内容混搭打开了大门 . 许多着名网站都提供JSONP服务,允许您通过预定义的API访问其内容 .

  • 8

    如果您正在使用PHP,那么解决起来非常简单 . 只需在处理请求的PHP页面的开头添加以下脚本:

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

    Warning: 这包含您的PHP文件的安全问题,攻击者可以调用它 . 您必须使用会话和cookie进行身份验证,以防止您的文件/服务遭受此攻击 . 您的服务容易受到cross-site request forgery(CSRF)的攻击 .

    如果您正在使用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"
    },
    
  • 62

    我希望有人在很久以前与我分享这个网站http://cors.io/与构建和依赖我自己的代理相比,它可以节省大量时间 . 但是,当您转向 生产环境 时,拥有自己的代理是最好的选择,因为您仍然可以控制数据的所有方面 .

    一切你需要的:

    https://cors.io/?http://HTTP_YOUR_LINK_HERE

  • 194

    如果您使用Node.js,请尝试:

    app.use(function(req, res, next) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        next();
    });
    

    更多信息:CORS on ExpressJS

  • 318

    因为
    $.ajax({type: "POST" - 致电 OPTIONS
    $.post( - 致电 POST

    两者都是不同的Postman称之为“POST”,但当我们称之为“OPTIONS”时

    For c# web services - webapi

    请在您的web.config中添加以下代码<system.webServer>标记下的文件 . 这会奏效

    <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");
        }
    });
    

    Angular 4问题请参考:http://www.hubfly.com/blog/solutions/how-to-fix-angular-4-api-call-issues/

    Note: 如果您正在寻找下载内容 from third party website ,那么 this will not help you . 您可以尝试以下代码,但不能使用JavaScript .

    System.Net.WebClient wc = new System.Net.WebClient();
    string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");
    
  • 4

    试试XDomain

    摘要:纯JavaScript CORS替代/ polyfill . 无需服务器配置 - 只需在要与之通信的域上添加proxy.html . 该库使用XHook挂钩所有XHR,因此XDomain应与任何库一起使用 .

  • 22

    如果你不想:

    • 在Chrome中停用网络安全

    • 使用JSONP

    • 使用第三方网站重新路由您的请求

    并且您确定您的服务器已启用CORS(此处测试CORS:http://www.test-cors.org/

    然后你需要在你的请求中传入origin参数 . 此来源必须与您的浏览器与您的请求一起发送的来源相匹配 .

    你可以在这里看到它:http://www.wikibackpacker.com/app/detail/Campgrounds/3591

    编辑功能将GET和POST请求发送到其他域以获取数据 . 我设置了解决问题的origin参数 . 后端是一个mediaWiki引擎 .

    tldr:在你的调用中添加“origin”参数,这些参数必须是浏览器发送的Origin参数(你不能欺骗origin参数)

  • 8

    当我使用AngularJS访问我的API时,我遇到了问题 . 相同的请求在SoapUI 5.0和ColdFusion中有效 . 我的GET方法已经有了Access-Control-Allow-Origin标头 .

    我发现了 AngularJS makes a "trial" OPTIONS request . 默认情况下,ColdFusion会生成OPTIONS方法,但它没有太多,具体来说这些标头 . 响应OPTIONS调用生成错误,而不是我故意调用GET . 在我将API OPTIONS方法添加到我的API后,问题已得到解决 .

    <cffunction name="optionsMethod" access="remote" output="false" returntype="any" httpmethod="OPTIONS" description="Method to respond to AngularJS trial call">
        <cfheader name="Access-Control-Allow-Headers" value="Content-Type,x-requested-with,Authorization,Access-Control-Allow-Origin"> 
        <cfheader name="Access-Control-Allow-Methods" value="GET,OPTIONS">      
        <cfheader name="Access-Control-Allow-Origin" value="*">      
        <cfheader name="Access-Control-Max-Age" value="360">        
    </cffunction>
    
  • 45

    从服务器请求响应时,我有以下配置,导致相同的错误 .

    Server-side: SparkJava - >提供REST-API
    Client-side: ExtJs6 - >提供浏览器渲染

    server-side 我必须将此添加到响应中:

    Spark.get("/someRestCallToSpark", (req, res) -> {
        res.header("Access-Control-Allow-Origin", "*"); //important, otherwise its not working 
        return "some text";
     });
    

    client-side 我必须将此添加到请求中:

    Ext.Ajax.request({
        url: "http://localhost:4567/someRestCallToSpark",
        useDefaultXhrHeader: false, //important, otherwise its not working
        success: function(response, opts) {console.log("success")},
        failure: function(response, opts) {console.log("failure")}
    });
    
  • 10

    基于shruti's answer,我创建了一个带有所需参数的Chrome浏览器快捷方式:
    enter image description here

    enter image description here

  • 3

    您可以通过使用YQL通过Yahoo的服务器代理请求来绕过问题 . 它只是几行代码:

    var yql_url = 'https://query.yahooapis.com/v1/public/yql';
    var url = 'your api url';
    
    $.ajax({
        'url': yql_url,
        'data': {
            'q': 'SELECT * FROM json WHERE url="'+url+'"',
            'format': 'json',
            'jsonCompat': 'new',
        },
        'dataType': 'jsonp',
        'success': function(response) {
            console.log(response);
        },
    });
    

    这是带有解释的链接:https://vverma.net/fetch-any-json-using-jsonp-and-yql.html

  • 158

    https://github.com/Rob--W/cors-anywhere/提供(Node.js)代码,您可以使用它来设置和运行自己的CORS代理 . 它主动维护并提供许多功能来控制代理行为,而不仅仅是基本发送正确的 Access-Control-* 响应头 .

    https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS有详细说明浏览器如何处理客户端Web应用程序通过JavaScript进行的跨源请求以及必须配置由服务器发送请求的头部,如果可以的话 .

    如果您需要向其发出请求并获得响应的站点未返回 Access-Control-Allow-Origin 响应标头,则浏览器始终会阻止客户端JavaScript代码直接向其发出的跨源请求 . 因此,如果站点不是您控制的站点并且可以为其配置行为,那么在这种情况下唯一可行的是代理请求 - 通过您自己运行的代理或通过开放代理 .

    正如在此处的其他评论中所提到的,有充分的理由不信任您的请求的开放代理 . 也就是说,如果您知道自己在做什么,并且您认为开放代理可以满足您的需求,那么https://cors-anywhere.herokuapp.com/是一个可靠,可靠,可维护且运行https://github.com/Rob--W/cors-anywhere/代码实例的代理 .

    与此处提到的其他开放代理(其中一些至少似乎不再可用)一样,它的工作方式是,不是让您的客户端代码直接发送请求,例如 http://foo.com ,您将其发送给 https://cors-anywhere.herokuapp.com/http://foo.com 并且代理将必要的 Access-Control-* 标头添加到浏览器看到的响应中 .

  • 1078

    如果您使用Entity Framework,即使启用了 CORS ,有时也会抛出此错误 . 我发现错误的发生是因为缺少查询的最终确定 . 我希望这会在同样的情况下帮助其他人 .

    以下代码可能会抛出 XMLHttpRequest cannot load http://myApiUrl/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. 错误:

    using (DBContext db = new DBContext())
    {
        return db.Customers.Select(x => new
        {
            Name = x.Name,
            CustomerId = x.CustomerId,
        });
    }
    

    要解决此问题,需要在查询结束时进行 .ToList().FirstOrDefault() 之类的终结调用,如下所示:

    using (DBContext db = new DBContext())
    {
        return db.Customers.Select(x => new
        {
            Name = x.Name,
            CustomerId = x.CustomerId,
        }).ToList();
    }
    
  • 65

    在我的情况下,我使用的是JEE7 JAX-RS应用程序,并且以下技巧对我来说非常有效:

    @GET
        @Path("{id}")
        public Response getEventData(@PathParam("id") String id) throws FileNotFoundException {
            InputStream inputStream = getClass().getClassLoader().getResourceAsStream("/eventdata/" + id + ".json");
            JsonReader jsonReader = Json.createReader(inputStream);
            return Response.ok(jsonReader.readObject()).header("Access-Control-Allow-Origin", "*").build();
        }
    
  • 7

    我成功地能够使用htaccess解决(在我的情况下使用字体),但很明显,OP的要求稍有不同 . 但您可以使用FileMatch模式并添加任何类型的扩展名,以便它不会产生交叉错误 .

    <IfModule mod_headers.c>
      <FilesMatch "\.(ttf|ttc|otf|eot|woff|woff2|font.css|css)$">
        Header set Access-Control-Allow-Origin "*"
      </FilesMatch>
    </IfModule>
    

    https://httpd.apache.org/docs/2.4/mod/core.html#filesmatch

  • 6

    热门问题 - 如果你已经阅读了这篇文章而另外没有其他任何内容有助于另一件事 . 如果您有一个CDN,如Akamai,Limelight或类似的CDN,您可能需要检查您拥有的资源URI的缓存密钥 . 如果它不包含Origin标头值,则可能在从另一个Origin请求时返回缓存的响应 . 我们只花了半天时间调试这个 . CDN配置已更新为仅包含我们的一些选定域的Origin值,并将其设置为null . 这似乎有效,并允许来自我们已知域的浏览器查看我们的资源 . 当然所有其他答案都是到达这里的先决条件,但如果CDN是您浏览器的第一跳,则需要查看 .

    在我们的案例中,我们可以看到一些请求进入我们的服务但不是几乎没有网站发送的卷 . 这向我们指出了CDN . 我们能够返回并看到原始请求是从直接请求提供的,而不是浏览器AJAX调用的一部分,并且不包括响应头Access-Control-Allow-Origin . 显然,CDN缓存了这个值 . Akamai CDN配置调整将原始请求标头值视为匹配的一部分似乎已使其适用于我们 .

  • 5

    对于GoLang API:

    首先你可以看看MDN CORS Doc来了解CORS是什么 . 据我所知,CORS是否允许Origin Of Request访问Server Resource .

    您可以通过在服务器响应的 Header 设置 Access-Control-Allow-Origin 来限制哪个请求源可以访问服务器 .

    例如,在服务器响应中设置以下标头意味着只有从 http://foo.example 发送的请求才能访问您的服务器:

    Access-Control-Allow-Origin: http://foo.example
    

    以及允许从任何来源(或域)发送的请求:

    Access-Control-Allow-Origin: *
    

    正如我在错误消息中所知, requested resource 表示服务器的资源,因此 No 'Access-Control-Allow-Origin' header is present on the requested resource. 表示您未在服务器响应中设置 Access-Control-Allow-Origin 标头,或者您可能设置但请求的来源不是 Access-Control-Allow-Origin 中的列表,因此不允许请求访问:

    请求的资源上不存在“Access-Control-Allow-Origin”标头 . 因此不允许原点'null'访问 .

    在GoLang中,我使用 gorilla/mux 包在 localhost:9091 构建API服务器,并通过将 "Access-Control-Allow-Origin", "*" 添加到响应头来允许CORS:

    func main() { // API Server Code
        router := mux.NewRouter()
        // API route is /people,
        //Methods("GET", "OPTIONS") means it support GET, OPTIONS
        router.HandleFunc("/people", GetPeople).Methods("GET", "OPTIONS")
        log.Fatal(http.ListenAndServe(":9091", router))
    }
    
    // Method of '/people' route
    func GetPeople(w http.ResponseWriter, r *http.Request) {
    
        // Allow CORS by setting * in sever response
        w.Header().Set("Access-Control-Allow-Origin", "*")
    
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
        json.NewEncoder(w).Encode("OKOK")
    }
    

    我在客户端使用JavaScript,在 localhost:9092 上,Chrome的请求可以成功从服务器 localhost:9091 获取"OKOK" .

    function GetPeople() {
        try {
            var xhttp = new XMLHttpRequest();
            xhttp.open("GET", "http://localhost:9091/people", false);
            xhttp.setRequestHeader("Content-type", "text/html");
            xhttp.send();
            var response = JSON.parse(xhttp.response);
            alert(xhttp.response);
        }
        catch (error) {
            alert(error.message);
        }
    }
    

    此外,您可以通过 Fiddler 等工具检查您的请求/响应标头 .

  • 4

    如果您从浏览器收到此错误消息:

    No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '…' is therefore not allowed access
    

    当您尝试向远程服务器执行Ajax POST / GET请求时,请忘记这个简单的修复:

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

    您真的需要,特别是如果您只使用JavaScript来执行Ajax请求,内部代理将接收您的查询并将其发送到远程服务器 .

    首先在您的JavaScript代码中,对您自己的服务器执行Ajax调用,例如:

    $.ajax({
        url: yourserver.com/controller/proxy.php,
        async: false,
        type: "POST",
        dataType: "json",
        data: data,
        success: function (result) {
            JSON.parse(result);
        },
        error: function (xhr, ajaxOptions, thrownError) {
            console.log(xhr);
        }
    });
    

    然后,创建一个名为proxy.php的简单PHP文件来包装POST数据,并将它们作为参数附加到远程URL服务器 . 我举例说明了如何使用Expedia Hotel搜索API绕过此问题:

    if (isset($_POST)) {
      $apiKey = $_POST['apiKey'];
      $cid = $_POST['cid'];
      $minorRev = 99;
    
      $url = 'http://api.ean.com/ean-services/rs/hotel/v3/list?' . 'cid='. $cid . '&' . 'minorRev=' . $minorRev . '&' . 'apiKey=' . $apiKey;
    
      echo json_encode(file_get_contents($url));
     }
    

    通过做:

    echo json_encode(file_get_contents($url));
    

    您只是在执行相同的查询,但在服务器端,之后,它应该可以正常工作 .

    Answer copied and pasted from NizarBsb

  • 4

    很多时候,这种情况发生在我从javascript到我的php api,因为有几个原因之一 . 我忘了把 <?php header('Access-Control-Allow-Origin: *'); ? 放在一边 . 这对跨子域访问很有帮助 . 另一个原因是因为在jQuery ajax请求中我指定了一个特定的dataType并返回一个不同的dataType,所以它抛出了一个错误 .

    此错误的最后和最突出的原因是您请求的页面上存在解析错误 . 如果您在浏览器中点击该页面网址的可能性很大,您将看到一个解析错误,并且您将有一个行号来解决该问题 .

    我希望这有帮助有人 . 我每次花了一段时间来调试这个,我希望我有一份要核实的清单 .

  • 2

    我在Angular中用 $http.get 得到了这个错误 . 我需要使用 $http.jsonp 代替 .

  • 2

    在我的网站上(基于.NET)我刚刚添加了这个:

    <system.webServer>
     <httpProtocol>  
        <customHeaders>  
         <add name="Access-Control-Allow-Origin" value="*" />  
         <add name="Access-Control-Allow-Headers" value="Content-Type" />  
         <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />  
        </customHeaders>  
      </httpProtocol>         
    </system.webServer>
    

    非常感谢this视频 .

  • 1

    CORS适合你 .

    CORS是“跨源资源共享”,是一种发送跨域请求的方法 . 现在,XMLHttpRequest2和Fetch API都支持CORS .

    但它有其局限性 . 服务器需要具体声明 Access-Control-Allow-Origin ,并且不能设置为'*' .

    如果你想任何来源可以发送请求给你,你需要JSONP(也需要设置 Access-Control-Allow-Origin ,但可以'*') .

    对于很多请求方式,如果你不知道该选择什么,我认为你需要一个功能齐全的组件来做到这一点 . 让我介绍一个简单的组件 catta


    如果您使用的是现代浏览器(> Internet Explorer9,Chrome,Firefox,Edge等),建议您使用简单但美观的组件 https://github.com/Joker-Jelly/catta . 它没有依赖关系,小于3 KB,它支持Fetch,Ajax和JSONP,具有相同的死语法和选项 .

    catta('./data/simple.json').then(function (res) {
      console.log(res);
    });
    

    它还支持导入项目的所有方式,如ES6模块,CommonJS甚至HTML中的 <script> .

  • 1

    这些答案中的大多数都告诉用户如何将CORS标头添加到他们控制的服务器中 .

    但是,如果您需要来自服务器的数据而无法在网页中控制,则一种解决方案是在页面上创建脚本标记,将src属性设置为不具有CORS标头的api endpoints ,然后加载该数据到页面上:

    window.handleData = function(data) {
      console.log(data)
    };
    
    var script = document.createElement('script');
    script.setAttribute('src','https://some.api/without/cors/headers.com&callback=handleData');
    document.body.appendChild(script);
    
  • 1

    如果你想在后端(在Flask中)修复它,而不是在前端,我会完全推荐Flask CORS python包 . Flask Cors

    使用app.py中的一个简单行,您可以自动插入标准允许任何原始 Headers ,或根据需要自定义它 .

  • 5

    对于 application_controller.rb 中的Ruby on Rails服务器,添加以下内容:

    after_action :cors_set_access_control_headers
    
    def cors_set_access_control_headers
      headers['Access-Control-Allow-Origin'] = '*'
      headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
      headers['Access-Control-Allow-Headers'] = '*'
    end
    
  • 2

    No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://sx.xyz.com' is therefore not allowed access.

    我在Ajax响应中也遇到了与跨域数据交换类似的问题 error undefined . 但 Headers 中的回复是 Status Code:200 OK

    Failed to load https://www.Domain.in/index.php?route=api/synchronization/checkapikey:
    No 'Access-Control-Allow-Origin' header is present on the requested resource.
    Origin 'https://sx.xyz.in' is therefore not allowed access.
    

    The solution to get around it: 在我的情况下,它是通过Ajax将函数checkapikey()调用到另一个域并获取响应数据到响应的位置:

    if (($this->request->server['REQUEST_METHOD'] == 'POST') && isset($this->request->server['HTTP_ORIGIN'])) {
    
            $this->response->addHeader('Access-Control-Allow-Origin: ' . $this->request->server['HTTP_ORIGIN']);
            $this->response->addHeader('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
            $this->response->addHeader('Access-Control-Max-Age: 1000');
            $this->response->addHeader('Access-Control-Allow-Credentials: true');
            $this->response->addHeader('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
    
            $headers = getallheaders();
    ...
    }
    
  • 2

    为完整起见,Apache允许角色:

    Header set Access-Control-Allow-Origin "http://www.allowonlyfromthisurl.com"
    Header set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
    Header set Access-Control-Max-Age "1000"
    Header set Access-Control-Allow-Headers "x-requested-with, Content-Type, Accept-Encoding, Accept-Language, Cookie, Referer"
    

相关问题