404

我有一个涉及的设置

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

浏览器 <-- webapp <-- Node.js(服务应用程序)

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

现在,我的问题是 webapp 用于对后端服务器进行 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 中,我正在使用这个中间件 和这个

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

10 回答 10

316

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

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

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

于 2013-11-02T17:31:56.523 回答
68

如果您使用 CORS 中间件并且想要发送withCredentialboolean true,则可以像这样配置 CORS:

var cors = require('cors');    
app.use(cors({credentials: true, origin: 'http://localhost:3000'}));
于 2017-08-26T00:30:16.120 回答
34

Expanding on @Renaud idea, cors now provides a very easy way of doing this:

From cors official documentation found here:

" origin: Configures the Access-Control-Allow-Origin CORS header. Possible values: Boolean - set origin to true to reflect the request origin, as defined by req.header('Origin'), or set it to false to disable CORS. "

Hence we simply do the following:

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

Lastly I think it is worth mentioning that there are use cases where we would want to allow cross origin requests from anyone; for example, when building a public REST API.

NOTE: I would have liked to leave this as a comment on his answer, but unfortunately I don't have the reputation points.

于 2020-10-23T16:47:20.950 回答
19

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

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

app.use(cors());

app.get(function(req,res){ 
  res.send('hello');
});
于 2013-11-02T15:22:58.810 回答
19

试试看:

const cors = require('cors')

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

}
app.use(cors(corsOptions));
于 2017-12-24T10:41:00.893 回答
13

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

app.use(cors({
  origin: function(origin, callback){
    return callback(null, true);
  },
  optionsSuccessStatus: 200,
  credentials: true
}));
于 2019-05-17T15:22:49.443 回答
6

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

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

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

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

于 2019-08-26T09:57:27.300 回答
3

(编辑)之前推荐的插件不再可用,您可以尝试另一个


为了在 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 模式添加到。要在此处添加的可使用的示例 URL 模式http://localhost:8080是:*://*

于 2018-12-30T09:58:33.463 回答
0

在执行请求之前,使用 auth 拦截器编辑标头有这个问题。我们使用 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);
  }

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

于 2020-06-30T12:49:45.150 回答
-10

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

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

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

示例: 在此处输入图像描述

祝你好运!

于 2021-07-20T12:55:53.917 回答