关于javascript:对预检请求的响应不通过访问控制检查

Response to preflight request doesn't pass access control check

使用ngresource调用Amazon Web服务上的REST API时出现此错误:

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

服务:

1
2
3
4
5
6
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'}
            });
}]);

控制器:

1
2
3
4
5
6
7
8
9
[...]
loginService.getUser(JSON.stringify(fbObj)),
                function(data){
                    console.log(data);
                },
                function(result) {
                    console.error('Error', result.status);
                }
[...]

我用的是Chrome,我不知道还能做什么来解决这个问题。我甚至将服务器配置为接受来自原始服务器localhost的头文件。


你遇到了CORS问题。

有几种方法可以解决这个问题。

  • 关闭CORS。例如:如何在chrome中关闭cors
  • 为浏览器使用插件
  • 使用一个代理,如nginx。如何设置的示例
  • 更确切地说,您正试图从本地主机访问api.serverurl.com。这是跨域请求的确切定义。

    通过关闭它只是为了完成你的工作(好吧,如果你访问其他站点,把你的安全性放在很差的地方,然后把罐子放在路边),你可以使用一个代理,让你的浏览器认为所有的请求都来自本地主机,而实际上你有本地服务器,然后调用远程服务器。

    所以api.serverurl.com可能成为localhost:8000/api,您的本地nginx或其他代理将发送到正确的目的地。

    现在,根据大众的需求,100%更多的CORS信息……同样的好味道!

    而对于落选者……对于那些只学习前端的人来说,绕过CORS正是所展示的。https://codecraft.tv/courses/angular/http/http-with-promises/


    我的"api服务器"是一个php应用程序,为了解决这个问题,我找到了下面的解决方案:

    将行放入index.php

    1
    2
    3
    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');


    在aspnetcore Web API中,通过添加"microsoft.aspnetcore.cors"(1.1.1版)和在startup.cs上添加以下更改,解决了这个问题。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
              options.AddPolicy("AllowAllHeaders",
                    builder =>
                {
                        builder.AllowAnyOrigin()
                               .AllowAnyHeader()
                               .AllowAnyMethod();
                    });
        });
        .
        .
        .
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {


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

    [EnableCors("AllowAllHeaders")]放在控制器上。


    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.

    资料来源:https://developer.mozilla.org/en-us/docs/web/http/access_control_cors

    您必须从服务器端发送访问控制allow origin:*HTTP头。

    如果您使用Apache作为HTTP服务器,那么可以将其添加到Apache配置文件中,如下所示:

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

    默认情况下,在Apache中会启用mod_头文件,但是,您可能希望通过运行以下命令来确保启用mod_头文件:

    1
     a2enmod headers


    如果你在写Chrome扩展名

    您必须在manifest.json中添加您的域的权限。

    1
    2
    3
    4
    "permissions": [
      "http://example.com/*",
      "https://example.com/*"
    ]


    说到CORS有一些注意事项。首先,它不允许使用通配符*,但不允许我使用这个。我在某个地方读过,现在找不到文章。

    如果您从其他域发出请求,则需要添加"允许来源"头。
    Access-Control-Allow-Origin: www.other.com

    如果您发出的请求会影响服务器资源,如post/put/patch,并且mime类型与下列application/x-www-form-urlencodedmultipart/form-datatext/plain不同,则浏览器将自动发出飞行前选项请求,以便在允许的情况下与服务器进行检查。

    因此,您的API/Server需要相应地处理这些选项请求,您需要使用适当的access control headers进行响应,HTTP响应状态代码需要为200

    标题应该是这样的,根据您的需要进行调整:
    Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
    Access-Control-Allow-Headers: Content-Type
    Access-Control-Max-Age: 86400
    max-age头很重要,在我的例子中,没有它就不能工作,我想浏览器需要"访问权限"有效期的信息。

    此外,如果您使用来自不同域的application/jsonmime发出POST请求,则还需要添加前面提到的允许来源头,因此看起来如下:


    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

    当飞行前成功并获得所有需要的信息时,您的实际请求将被提出。

    一般来说,无论在初始或飞行前请求什么Access-Control报头,都应该在响应中给出,以便其工作。

    在这个链接的MDN文档中有一个很好的例子,您还应该查看这个so post


    如果您偶然使用了IIS服务器。您可以在HTTP请求头选项中设置以下头。

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

    有了这一切,GET等工作都会很好。


    在PHP中,您可以添加头文件:

    1
    2
    3
    4
    5
    6
    <?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: *");
    ...


    对于python flask服务器,可以使用flask cors插件来启用跨域请求。

    参见:https://flask-cors.readthedocs.io/en/latest/


    要修复节点JS应用程序中的跨源请求问题,请执行以下操作:

    1
    npm i cors

    只需将下面的行添加到EDOCX1[0]

    1
    2
    let cors = require('cors')
    app.use(cors())


    我们的团队偶尔会使用Vue、AXIOS和C WebAPI看到这一点。在您试图点击的端点上添加一个路由属性,可以为我们修复它。

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


    此错误的一个常见原因可能是主机API已将请求映射到HTTP方法(例如Put),而API客户端正在使用其他HTTP方法(例如Post或Get)调用API。


    在我的apache virtualhost配置文件中,我添加了以下行:

    1
    2
    3
    4
    5
    6
    7
    8
    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]

    对于那些使用lambda集成代理和API网关的用户。您需要像直接向lambda提交请求一样配置lambda函数,这意味着该函数应该正确设置响应头。(如果您使用自定义lambda函数,这将由API网关处理。)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //In your lambda's index.handler():
    exports.handler = (event, context, callback) => {
         //on success:
         callback(null, {
               statusCode: 200,
               headers: {
                   "Access-Control-Allow-Origin" :"*"
               }
         }
    }


    geoserver的独立发行版包括jetty应用服务器。启用跨源站资源共享(CORS)允许您自己域之外的javascript应用程序使用geoserver。

    从webapps/geoserver/web-inf/web.xml中取消对以下的注释:

    10


    我正在使用awsdk进行上传,在花了一些时间在线搜索之后,我偶然发现了这个线程。多亏了@lsimoneau 45581857,事实证明发生了完全相同的事情。我只是通过附加区域选项将请求URL指向bucket上的区域,它就工作了。

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

    当DNS服务器设置为8.8.8.8(Google)时,我遇到了这个问题。实际上,问题出在路由器上,我的应用程序试图通过谷歌与服务器连接,而不是本地连接(针对我的特定情况)。我删除了8.8.8.8,这解决了这个问题。我知道这个问题是通过CORS设置解决的,但也许有人会和我有同样的麻烦。


    我认为从铬中禁用CORS不是一个好方法,因为如果你在爱奥尼亚中使用它,当然在移动构建中这个问题会再次出现。

    所以最好在后端修复。

    首先,你需要设置-

    • header('access-control-allow-origin:*');
    • header('header set access control allow headers:"origin,x-requested-with,content-type,accept"');

    如果api同时表现为get和post,那么也在头部设置-

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


    很容易错过的东西…

    在解决方案资源管理器中,右键单击API项目。在"属性"窗口中,将"匿名身份验证"设置为"已启用"!!!!


    禁用Chrome安全。创建Chrome快捷方式右键单击->属性->目标,粘贴此"c:Program Files(x86)GoogleChromeApplicationChrome.exe"--禁用Web安全--用户数据dir="c:/Chromedev"