Response to preflight request doesn't pass acc

2018-12-31 14:35发布

问题:

I\'m getting this error using ngResource to call a REST API on Amazon Web Services:

XMLHttpRequest cannot load http://server.apiurl.com:8000/s/login?login=facebook. Response to preflight request doesn\'t pass access control check: No \'Access-Control-Allow-Origin\' header is present on the requested resource. Origin \'http://localhost\' is therefore not allowed access. Error 405

Service:

socialMarkt.factory(\'loginService\', [\'$resource\', function($resource){    
    var apiAddress = \"http://server.apiurl.com:8000/s/login/\";
    return $resource(apiAddress, { login:\"facebook\", access_token: \"@access_token\" ,facebook_id: \"@facebook_id\" }, {
                getUser: {method:\'POST\'}
            });
}]);

Controller:

[...]
loginService.getUser(JSON.stringify(fbObj)),
                function(data){
                    console.log(data);
                },
                function(result) {
                    console.error(\'Error\', result.status);
                }
[...]

I\'m using Chrome, and I dont know what else to do in order to fix this problem. I\'ve even configured the server to accept headers from origin localhost.

回答1:

You are running into CORS issues.

There are several ways to fix/workaround this.

  1. Turn off CORS. For example: how to turn off cors in chrome
  2. Use a plugin for your browser
  3. Use a proxy such as nginx. example of how to set up

More verbosely, you are trying to access api.serverurl.com from localhost. This is the exact definition of cross domain request.

By either turning it off just to get your work done (OK, put poor security for you if you visit other sites and just kicks the can down the road) you can use a proxy which makes your browser think all requests come from local host when really you have local server that then calls the remote server.

so api.serverurl.com might become localhost:8000/api and your local nginx or other proxy will send to the correct destination.


Now by popular demand, 100% more CORS info....same great taste!


And for the downvoters.... bypassing CORS is exactly what is shown for those simply learning the front end. https://codecraft.tv/courses/angular/http/http-with-promises/



回答2:

My \"API Server\" is an PHP Application so to solve this problem I found the below solution to work:

Place the lines in index.php

header(\'Access-Control-Allow-Origin: *\');
header(\'Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS\');
header(\'Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token\');


回答3:

In AspNetCore web api, this issue got fixed by adding \"Microsoft.AspNetCore.Cors\" (ver 1.1.1) and adding the below changes on Startup.cs.

public void ConfigureServices(IServiceCollection services)
{ 
    services.AddCors(options =>
    {
          options.AddPolicy(\"AllowAllHeaders\",
                builder =>
            {
                    builder.AllowAnyOrigin()
                           .AllowAnyHeader()
                           .AllowAnyMethod();
                });
    });
    .
    .
    .
}

and

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{


    // Shows UseCors with named policy.
    app.UseCors(\"AllowAllHeaders\");
    .
    .
    .
}

and putting [EnableCors(\"AllowAllHeaders\")] on the controller.



回答4:

JavaScript XMLHttpRequest and Fetch follow the same-origin policy. So, a web application using XMLHttpRequest or Fetch could only make HTTP requests to its own domain.

Source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

You have to send the Access-Control-Allow-Origin: * HTTP header from your server side.

If you are using Apache as your HTTP server then you can add it to your Apache configuration file like this:

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

Mod_headers is enabled by default in Apache, however, you may want to ensure it\'s enabled by running:

 a2enmod headers


回答5:

If you\'re writing a chrome-extension

You have to add in the manifest.json the permissions for your domain(s).

\"permissions\": [
   \"http://example.com/*\",
   \"https://example.com/*\"
]


回答6:

For python flask server, you can use the flask-cors plugin to enable cross domain requests.

See : https://flask-cors.readthedocs.io/en/latest/



回答7:

If you are using IIS server by chance. you can set below headers in the HTTP request headers option.

Access-Control-Allow-Origin:*
Access-Control-Allow-Methods: \'HEAD, GET, POST, PUT, PATCH, DELETE\'
Access-Control-Allow-Headers: \'Origin, Content-Type, X-Auth-Token\';

with this all post, get etc., will work fine.



回答8:

In PHP you can add the headers:

<?php
header (\"Access-Control-Allow-Origin: *\");
header (\"Access-Control-Expose-Headers: Content-Length, X-JSON\");
header (\"Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS\");
header (\"Access-Control-Allow-Headers: *\");
...


回答9:

In my Apache VirtualHost config file, I have added following lines :

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\"

RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]


回答10:

For those are using Lambda Integrated Proxy with API Gateway. You need configure your lambda function as if you are submitting your requests to it directly, meaning the function should set up the response headers properly. (If you are using custom lambda functions, this will be handled by the API Gateway.)

//In your lambda\'s index.handler():
exports.handler = (event, context, callback) => {
     //on success:
     callback(null, {
           statusCode: 200,
           headers: {
                \"Access-Control-Allow-Origin\" : \"*\"
           }
     }
}


回答11:

There are some caveats when it comes to CORS. First, it does not allow wildcards * but don\'t hold me on this one I\'ve read it somewhere and I can\'t find the article now.

If you are making requests from a different domain you need to add the allow origin headers. Access-Control-Allow-Origin: www.other.com

If you are making requests that affect server resources like POST/PUT/PATCH, and if the mime type is different than the following application/x-www-form-urlencoded, multipart/form-data, or text/plain the browser will automatically make a pre-flight OPTIONS request to check with the server if it would allow it.

So your API/server needs to handle these OPTIONS requests accordingly, you need to respond with the appropriate access control headers and the http response status code needs to be 200.

The headers should be something like this, adjust them for your needs: Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS Access-Control-Allow-Headers: Content-Type Access-Control-Max-Age: 86400 The max-age header is important, in my case, it wouldn\'t work without it, I guess the browser needs the info for how long the \"access rights\" are valid.

In addition, if you are making e.g. a POST request with application/json mime from a different domain you also need to add the previously mentioned allow origin header, so it would look like this:

Access-Control-Allow-Origin: www.other.com Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS Access-Control-Allow-Headers: Content-Type Access-Control-Max-Age: 86400

When the pre-flight succeeds and gets all the needed info your actual request will be made.

Generally speaking, whatever Access-Control headers are requested in the initial or pre-flight request, should be given in the response in order for it to work.

There is a good example in the MDN docs here on this link, and you should also check out this SO post



回答12:

The standalone distributions of GeoServer include the Jetty application server. Enable Cross-Origin Resource Sharing (CORS) to allow JavaScript applications outside of your own domain to use GeoServer.

Uncomment the following <filter> and <filter-mapping> from webapps/geoserver/WEB-INF/web.xml:

<web-app>
  <filter>
      <filter-name>cross-origin</filter-name>
      <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>cross-origin</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>


回答13:

I think disabling CORS from Chrome is not good way, because if you are using it in ionic, certainly in Mobile Build the Issue will raise Again.

So better to Fix in your Backend.

First of all In header, you need to set-

  • header(\'Access-Control-Allow-Origin: *\');
  • header(\'Header set Access-Control-Allow-Headers: \"Origin, X-Requested-With, Content-Type, Accept\"\');

And if API is behaving as GET and POST both then also Set in your header-

if ($_SERVER[\'REQUEST_METHOD\'] == \'OPTIONS\') { if (isset($_SERVER[\'HTTP_ACCESS_CONTROL_REQUEST_METHOD\'])) header(\"Access-Control-Allow-Methods: GET, POST, OPTIONS\");
if (isset($_SERVER[\'HTTP_ACCESS_CONTROL_REQUEST_HEADERS\'])) header(\"Access-Control-Allow-Headers:
{$_SERVER[\'HTTP_ACCESS_CONTROL_REQUEST_HEADERS\']}\"); exit(0); }



回答14:

A very common cause of this error could be that the host API had mapped the request to a http method (e.g. PUT) and the API client is calling the API using a different http method (e.g. POST or GET)



回答15:

The issue is happens due to cross-origin-requests

npm i cors

Simply add below lines to nodejs project\'s app.js

let cors = require(\'cors\') app.use(cors())



回答16:

I have faced with this problem when DNS server was set to 8.8.8.8 (google\'s). Actually, the problem was in router, my application tried to connect with server through the google, not locally (for my particular case). I have removed 8.8.8.8 and this solved the issue. I know that this issues solved by CORS settings, but maybe someone will have the same trouble as me



回答17:

Something that is very easy to miss...

IN solution explorer, right-click api-project. In properties window set \'Anonymous Authentication\' to Enabled !!!



回答18:

I am using AWS sdk for uploads, after spending some time searching online i stumbled upon this thread. thanks to @lsimoneau 45581857 its turns out the exact same thing was happening. I simply pointed my request Url to the region on my bucket by attaching the region property and it worked.

 const s3 = new AWS.S3({
 accessKeyId: config.awsAccessKeyID,
 secretAccessKey: config.awsSecretAccessKey,
 region: \'eu-west-2\'  // add region here });


回答19:

Our team occasionally sees this using Vue, axios and a C# WebApi. Adding a route attribute on the endpoint you\'re trying to hit fixes it for us.

[Route(\"ControllerName/Endpoint\")]
[HttpOptions, HttpPost]
public IHttpActionResult Endpoint() { }


回答20:

Disable the chrome security.Create a chrome shortcut right click -> properties -> target, paste this \"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe\" --disable-web-security --user-data-dir=\"c:/chromedev\"