CORS:当凭据标志为true时,不能在Access-Control-Allow-Origin中使用通配符


295

我有一个涉及的设置

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

浏览器<-webapp <-Node.js(为应用提供服务)

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

现在,我的问题是CORS设置,Web应用程序使用它来对后端服务器进行Ajax调用。在Chrome中,我不断

当凭据标志为true时,不能在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我使用这个中间件 与此相伴

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配置:

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/
)

1
对我来说,它是没有http的localhost:3000,例如:CORS_ORIGIN_WHITELIST =('localhost:3000',)
Andrei

您是说要在一台PC上开发前端和后端吗?
fanhualuojin154873

不同的PC的前端和后端如何?
fanhualuojin154873

@ixaxaar为什么用http说适合您?我们都只有`'localhost:3000'`有效。
244boy

@ 244boy是的,重点不是末尾http,而是/末尾。我想省略http可以工作,但是几年来我一直没有真正从事过这项工作,所以现在真的不知道什么可行!
ixaxaar

Answers:


247

这是安全的一部分,您不能这样做。如果要允许凭据,则Access-Control-Allow-Origin不得使用*。您将必须指定确切的协议+域+端口。供参考,请参阅以下问题:

  1. Access-Control-Allow-Origin通配符子域,端口和协议
  2. 跨源资源共享凭证

除此以外,*这太宽松了,会打败凭据的使用。因此,将其设置为http://localhost:3000http://localhost:8000作为allow origin标头。


45
但是,如果有多个域怎么办?
aroth,2014年

13
@aroth您可以提供域列表。相关问题:stackoverflow.com/questions/1653308/...
user568109

13
@ user568109您能解释一下“此外*,太宽容了,并且会破坏凭据的使用。”?
雨果·伍德

12
如果请求来自移动设备(例如Cordova可能发生的情况),那么“确切域”是什么?
基督教徒

8
@Christian有点老,但是如果有人仍然好奇,此问题仅发生在运行于浏览器上的应用程序,因为出于安全原因浏览器会抛出此错误。使用HTTP客户端发出请求的其他客户端(例如移动应用程序,邮递员或任何其他后端代码)将不会出现此问题,因此您不必担心来源和确切的域
Alisson

32

如果使用的是CORS中间件,并且要发送withCredential布尔值true,则可以这样配置CORS:

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

16

如果您正在使用express,则可以使用cors包允许CORS这样进行操作,而不必编写中间件。

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

app.use(cors());

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

12
嗯,现在更方便了,但是结果是一样的:(顺便说一句,我正在使用app.use(cors({credentials: true}));
ixaxaar13年

1
你可能想看看这个被测试的Django CORS中间件。
2013年

1
因此,您有两个Django中间件?我只会使用django-cors-header应用程序。确保将localhost添加到CORS_ORIGIN_WHITELIST设置并设置CORS_ALLOW_CREDENTIALSTrue
Bulkan

1
是男人,试过之前都无济于事,有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
ixaxaar

5
阅读此文档后:github.com/expressjs/corsuse 我使用以下配置:app.use(cors({credentials:true,origin:' localhost:3001 '})); 为我工作。
allel

11

尝试一下:

const cors = require('cors')

const corsOptions = {
    origin: 'http://localhost:4200',
    credentials: true,

}
app.use(cors(corsOptions));

6

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

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

@TSlegaitis哈哈是的,这就是为什么它适用于所有来源但保留凭据的原因。为了安全起见,我不推荐使用它,但是它确实起作用。
松鼠

2

(编辑)以前推荐的加载项不再可用,您可以尝试其他的加载项


为了在Chrome中进行开发,安装 此附加组件将摆脱该特定错误:

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.

安装后,Intercepted URLs通过单击AddOn的(CORS,绿色或红色)图标并填充适当的文本框,确保将URL模式添加到。可以在此处添加的示例网址格式为http://localhost:8080*://*


安装后我就知道了,有什么想法吗?
哈利勒

它为我工作。警告,如果您有其他类似的加载项,请在尝试该插件之前先将其卸载。
FilippoG

请修复断开的链接
卢克·阿隆

好像原来的附加内容已被删除,我在顶部添加了一个新建议((编辑))
eriel marimon

1

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

您可以从请求中获取来源,然后在响应标头中使用该来源。这是快递的外观:

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

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


Mozilla Dev Docs扩展了将允许的来源更改为请求中的来源的想法。建议添加“ Vary:Origin” HTTP响应标头和白名单允许的域。
Ramzis
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.