Why does my JavaScript code get a “No 'Access-

2020-01-22 10:43发布

问题:

I am trying to do authorization using JavaScript by connecting to the RESTful API built in Flask. However, when I make the request, I get the following error:

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.

I know that the API or remote resource must set the header, but why did it work when I made the request via the Chrome extension Postman?

This is the request code:

$.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);
    });

回答1:

If I understood it right you are doing an XMLHttpRequest to a different domain than your page is on. So the browser is blocking it as it usually allows a request in the same origin for security reasons. You need to do something different when you want to do a cross-domain request. A tutorial about how to achieve that is Using CORS.

When you are using postman they are not restricted by this policy. Quoted from 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.



回答2:

This is not a fix for production or when application has to be shown to the client, this is only helpful when UI and Backend development are on different servers and in production they are actually on same server. For example: While developing UI for any application if there is a need to test it locally pointing it to backend server, in that scenario this is the perfect fix. For production fix, CORS headers has to be added to the backend server to allow cross origin access.

The easy way is to just add the extension in google chrome to allow access using CORS.

(https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf?hl=en-US)

Just enable this extension whenever you want allow access to no 'access-control-allow-origin' header request.

Or

In Windows, paste this command in run window

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

this will open a new chrome browser which allow access to no 'access-control-allow-origin' header request.



回答3:

If you can deal with JSON in return, then try using JSONP (note the P at the end) for speaking between domains:

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

Learn more about working with JSONP here:

The advent of JSONP — essentially a consensual cross-site scripting hack — has opened the door to powerful mashups of content. Many prominent sites provide JSONP services, allowing you access to their content via a predefined API.



回答4:

Warning: Using this answer on production may cause a security issue that your API/service could be called by anyone has the URL including attackers. you have to use sessions and cookies for authentication to prevent your API/service against this attack. Your API/service is vulnerable to cross-site request forgery (CSRF).

It's very simple to solve if you are using PHP. Just add the following script in the beginning of your PHP page which handles the request:

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

If you are using Node-red you have to allow CORS in the node-red/settings.js file by un-commenting the following lines:

// 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"
},

If you are using Flask same as the question; you have first to install flask-cors

$ pip install -U flask-cors

Then include the flask cors in your app

from flask_cors import CORS

A simple app will look like

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

For more details, you can check the flask documentation



回答5:

I wish someone shared this site with me long ago http://cors.io/ it would have saved a ton of time compared to building and relying on my own proxy. However, as you move to production, having your own proxy is the best bet since you still control all aspects of your data.

All you need:

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



回答6:

If you are using Node.js, try it:

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

More information: CORS on ExpressJS



回答7:

There's a cross-domain issue using Ajax. You must be sure you are accessing your files on the same http:// path without www. (or access from http://www. and post to the same path including www.) which the browser considers as another domain when accessing via a www. path, so you see where the problem is. You are posting to a different domain and the browser blocks the flow because of the origin issue.

If the API is not placed on the same host that you are requesting from, the flow is blocked, and you will need to find another way to communicate with the API.



回答8:

Because
$.ajax({type: "POST" - Calls OPTIONS
$.post( - Calls POST

both are different Postman calls "POST" properly but when we call it will be "OPTIONS"

For c# web services - webapi

Please add the following code in your web.config file under <system.webServer> tag. This will work

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

Please make sure you are not doing any mistake in the ajax call

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 issue please refer : http://www.hubfly.com/blog/solutions/how-to-fix-angular-4-api-call-issues/

Note: If you are looking for downloading content from third party website then this will not help you. You can try the following code but not JavaScript.

System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");
share|improve this answer