【问题标题】:CORS: Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is trueCORS:当凭据标志为真时,无法在 Access-Control-Allow-Origin 中使用通配符
【发布时间】:2014-07-08 13:07:58
【问题描述】:

我有一个涉及

的设置

前端服务器(Node.js,域:localhost:3000) 后端(Django,Ajax,域:localhost:8000)

浏览器

浏览器 (webapp) --> Ajax --> Django(服务 ajax POST 请求)

现在,我的问题在于 Web 应用程序用于对后端服务器进行 Ajax 调用的 CORS 设置。在 chrome 中,我不断得到

当凭证标志为真时,不能在 Access-Control-Allow-Origin 中使用通配符。

在 Firefox 上也不起作用。

我的 Node.js 设置是:

var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', 'http://localhost:8000/');
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
};

在 Django 中,我使用的是 this middleware along with this

webapp 发出这样的请求:

$.ajax({
    type: "POST",
    url: 'http://localhost:8000/blah',
    data: {},
    xhrFields: {
        withCredentials: true
    },
    crossDomain: true,
    dataType: 'json',
    success: successHandler
});

因此,webapp 发送的请求标头如下所示:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"
Access-Control-Allow-Methods: 'GET,PUT,POST,DELETE'
Content-Type: application/json 
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Cookie: csrftoken=***; sessionid="***"

这是响应标头:

Access-Control-Allow-Headers: Content-Type,*
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE
Content-Type: application/json

我哪里错了?!

编辑 1:我一直在使用 chrome --disable-web-security,但现在希望事情能够真正发挥作用。

编辑 2:答案:

所以,我的解决方案django-cors-headers config:

CORS_ORIGIN_ALLOW_ALL = False
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
    'http://localhost:3000' # Here was the problem indeed and it has to be http://localhost:3000, not http://localhost:3000/
)

【问题讨论】:

  • 对我来说是没有http的localhost:3000,像这样:CORS_ORIGIN_WHITELIST = ('localhost:3000',)
  • 你的意思是在一台PC上开发前端和后端?
  • 不同PC的前端和后端怎么样?
  • @ixaxaar 为什么你说 http 对你有用?我们都只有 ''localhost:3000'' 有效。
  • @244boy 是的,重点不是http,而是最后的/。我想省略 http 可能会起作用,但我已经有几年没有真正研究过这个东西了,所以现在真的不知道什么有效!

标签: ajax django node.js cors django-cors-headers


【解决方案1】:

如果您使用express,您可以使用cors 包来允许这样的CORS,而不是编写中间件;

var express = require('express')
, cors = require('cors')
, app = express();

app.use(cors());

app.get(function(req,res){ 
  res.send('hello');
});

【讨论】:

  • 啊,现在这样更方便了,但是结果是一样的:(顺便说一句,我使用的是app.use(cors({credentials: true}));
  • 您可能想查看经过测试的this Django CORS 中间件。
  • 那么你有两个 Django 中间件?我只会使用django-cors-header 应用程序。确保将 localhost 添加到 CORS_ORIGIN_WHITELIST 设置并将 CORS_ALLOW_CREDENTIALS 设置为 True
  • 是的,伙计,之前尝试过但无济于事,有CORS_ORIGIN_ALLOW_ALL = TrueCORS_ORIGIN_WHITELIST = ( 'localhost' )CORS_ALLOW_CREDENTIALS = True 我得到了这些标题:Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: http://localhost:3000/ Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE Content-Type: application/json
  • 阅读本文档后:github.com/expressjs/corsuse 我使用此配置:app.use(cors({credentials: true, origin: 'localhost:3001'}));正在为我工​​作。
【解决方案2】:

这是安全的一部分,你不能这样做。如果您想允许凭据,那么您的Access-Control-Allow-Origin 不得使用*。您必须指定确切的协议 + 域 + 端口。参考这些问题:

  1. Access-Control-Allow-Origin wildcard subdomains, ports and protocols
  2. Cross Origin Resource Sharing with Credentials

此外,* 过于宽松,会破坏凭据的使用。所以将http://localhost:3000http://localhost:8000 设置为允许源头。

【讨论】:

  • 但是如果有多个域怎么办?
  • @aroth 您可以提供域列表。相关问题:stackoverflow.com/questions/1653308/…
  • @user568109 你能否解释一下“除了* 过于宽松,会破坏凭据的使用。”?
  • 如果请求来自移动设备,那么“确切域”是什么,就像 Cordova 可能发生的那样?
  • @Christian 有点老了,但如果有人仍然好奇,这个问题只会发生在浏览器上运行的应用程序上,因为出于安全原因,浏览器会抛出这个错误。其他客户端(例如移动应用、邮递员或任何其他使用 http 客户端发出请求的后端代码)不会有此问题,因此您不必担心来源和确切域 .
【解决方案3】:

如果你正在使用 CORS 中间件并且你想发送 withCredential boolean true,你可以像这样配置 CORS:

var cors = require('cors');    
app.use(cors({credentials: true, origin: 'http://localhost:3000'}));

【讨论】:

    【解决方案4】:

    试试看:

    const cors = require('cors')
    
    const corsOptions = {
        origin: 'http://localhost:4200',
        credentials: true,
    
    }
    app.use(cors(corsOptions));
    

    【讨论】:

      【解决方案5】:

      (编辑)之前推荐的插件已经不可用了,你可以试试this other one


      为了在 Chrome 中进行开发,安装 this add on 将摆脱该特定错误:

      Access to XMLHttpRequest at 'http://192.168.1.42:8080/sockjs-node/info?t=1546163388687' 
      from origin 'http://localhost:8080' has been blocked by CORS policy: The value of the 
      'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' 
      when the request's credentials mode is 'include'. The credentials mode of requests 
      initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
      

      安装后,请确保通过单击 AddOn(CORS,绿色或红色)图标并填写相应的文本框,将您的 url 模式添加到 Intercepted URLs。要在此处添加的适用于 http://localhost:8080 的示例 URL 模式是:*://*

      【讨论】:

      • 我是刚安装的,有什么想法吗?
      • 它对我有用。警告如果您有其他类似的附加组件,您必须在尝试此之前将其卸载。
      • 请修复损坏的链接
      • 好像原来的插件被删除了,我在顶部添加了一个新的推荐作为(编辑)
      【解决方案6】:

      如果您想允许所有来源并保持凭据真实,这对我有用:

      app.use(cors({
        origin: function(origin, callback){
          return callback(null, true);
        },
        optionsSuccessStatus: 200,
        credentials: true
      }));
      

      【讨论】:

      • @TSlegaitis 哈哈是的,这就是为什么它适用于所有来源但保留凭据的原因。出于安全考虑,我不推荐它,但它确实有效。
      【解决方案7】:

      这在开发中对我有用,但我不能建议在生产中,这只是完成工作的另一种方式,尚未提及但可能不是最好的。无论如何,这里是:

      您可以从请求中获取来源,然后在响应标头中使用它。下面是它在 express 中的样子:

      app.use(function(req, res, next) {
        res.header('Access-Control-Allow-Origin', req.header('origin') );
        next();
      });
      

      我不知道你的 python 设置会是什么样子,但应该很容易翻译。

      【讨论】:

      • Mozilla Dev Docs 扩展了将允许的来源更改为请求来源的想法。建议添加 'Vary: Origin' HTTP 响应标头并将允许的域列入白名单。
      【解决方案8】:

      在执行请求之前,使用身份验证拦截器编辑标头时遇到了这个问题。我们使用 api-token 进行身份验证,所以我启用了凭据。现在,似乎不再需要/允许了

      @Injectable()
      export class AuthInterceptor implements HttpInterceptor {
        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
          req = req.clone({
            //withCredentials: true, //not needed anymore
            setHeaders: {
              'Content-Type' : 'application/json',
              'API-TOKEN' : 'xxx'
            },
          });
          
          return next.handle(req);
        }
      

      除此之外,目前没有副作用。

      【讨论】:

        【解决方案9】:

        扩展@Renaud 的想法,cors 现在提供了一种非常简单的方法:

        从cors官方文档中找到here

        " origin:配置 Access-Control-Allow-Origin CORS 标头。 可能的值: Boolean - 将 origin 设置为 true 以反映由 req.header('Origin') 定义的请求来源,或将其设置为 false 以禁用 CORS。 "

        因此我们只需执行以下操作:

        const app = express();
        const corsConfig = {
            credentials: true,
            origin: true,
        };
        app.use(cors(corsConfig));
        

        最后,我认为值得一提的是,在某些用例中,我们希望允许来自任何人的跨源请求;例如,在构建公共 REST API 时。

        注意: 我本来希望将此作为对他的回答的评论,但不幸的是我没有声誉积分。

        【讨论】:

        • 我喜欢这个答案!特别是关于在某些用例中您希望允许所有来源的事实(这里的许多答案似乎都认为这总是一种不好的做法)。
        【解决方案10】:

        注意:此解决方案仅用于测试目的,不应作为最终解决方案。

        一种快速简单的解决方法是通过在浏览器快捷方式属性中包含以下参数来禁用 CORS:

        --disable-web-security --user-data-dir="[c:]"

        示例:

        祝你好运!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-08-19
          • 2014-12-12
          • 2017-01-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多