在Access-Control-Allow-Origin中使用通配符作为子域

时间:2016-10-24 06:55:09

标签: ajax express xmlhttprequest cors

我在我的网站上使用Express并使用凭证xhr。我想从http://example.comhttp://admin.example.com请求http://service1.example.com,这是我在快递服务器中的Access-Control-Allow-Origin部分:

// CORS
app.use((req, res, next) => {
    res.setHeader('Access-Control-Allow-Origin', 'http://*.example.com');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
    next();
});

但是当我尝试从 http://admin.example.com http://example.com 的凭证xhr时,它失败了:

  

Fetch API无法加载http://example.com/api/v1/authentication/signin。   对预检请求的响应没有通过访问控制检查:   ' Access-Control-Allow-Origin'标头的值为' http://*.example.com'   这不等于提供的原产地。起源   ' http://admin.example.com'因此不允许访问。有   服务器发送带有效值的标头,或者,如果是不透明的响应   满足您的需求,将请求模式设置为“无人”状态。去取   CORS禁用的资源。

它看起来似乎是因为浏览器没有理解*.example.com的确切含义,并拒绝了该请求。

我想从这些域名请求:

  • example.com
  • admin.example.com
  • service1.example.com
  • service2.example.com
  • [什么] .example.com的

我使用Fetch API进行XHR,并设置credentials: true。有没有我错过的东西?任何建议都会非常感激。

3 个答案:

答案 0 :(得分:3)

我同意Derric的评论。另一件事是原始标题可能是欺骗性的,因此这不是一个安全的解决方案。

app.use(function (req, res, next) {
  if (req.headers.origin.endsWith('example.com')) {
    res.setHeader('Access-Control-Allow-Origin', 'http://' + req.headers.origin)
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type')
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE')
  }
  next()
})

答案 1 :(得分:1)

  

首先,IIRC;表达文档明确要求您不要使用   中间件的lambda表达式。

出现CORS问题,通配符子域在上下文中无效。最近(May '16)添加了支持,直到那时,the CORS header must be an exact match of the domain name

但是,您可以处理req.hostname值并将其添加到响应标头中:

// CORS
app.use(function (req, res, next) {
    if (req.hostname.endsWith('example.com')) {
        res.setHeader('Access-Control-Allow-Origin', 'http://' + req.hostname)
        res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type')
        res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE')
    }
    next()
})

答案 2 :(得分:1)

在这里添加另一个小调整。我们还应该考虑“协议”:

app.use(function (req, res, next) {
  if (req.headers.origin.endsWith('example.com')) {
    res.setHeader('Access-Control-Allow-Origin', req.protocol + '://' + req.headers.origin)
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type')
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE')
  }
  next()
})