我正在编写Golang API。 我对cors使用以下功能

1
2
3
4
5
6
func ResponseWithJSON(w http.ResponseWriter, json []byte, code int) {
    w.Header().Set("Content-Type","application/json; charset=utf-8")
    w.Header().Set("Access-Control-Allow-Origin","*")
    w.WriteHeader(code)
    w.Write(json)
}

这使任何人都可以访问我的api。 我想将其限制为我的域名。 因为听起来更安全。 让我们称之为www.example.com

我可以将其更改为

1
 w.Header().Set("Access-Control-Allow-Origin","http://www.example.com")

当网址为www.example.com而不是example.com时,这将允许我拨打电话

然后我可以将其更改为

1
w.Header().Set("Access-Control-Allow-Origin","http://example.com")

现在,我可以从example.com访问我的api,但不能从www.example.com访问

两者都不添加
都不是这样

1
w.Header().Set("Access-Control-Allow-Origin","http://www.example.com,http://example.com")

也没有这种方式

1
2
w.Header().Set("Access-Control-Allow-Origin","http://www.example.com")
w.Header().Set("Access-Control-Allow-Origin","http://example.com")

那么,有没有办法让我获得请求的原产地? 这样我就可以动态允许域了吗? 我还有另一种解决这个问题的方法吗?

  • 检查请求host标头并相应地提供响应。
  • 我怎么做?你有什么例子吗?
  • stackoverflow.com/q/42921567/251311
  • FWIW,Header.Set()不能多次设置相同的标头,因为它会替换以前设置的任何值。而是使用Header.Add()
  • 不,那是行不通的。现在它说Access-Control-Allow-Origin标头包含多个值
  • 如果两者都想尝试,请执行以下操作:w.Header().Set("Access-Control-Allow-Origin","http:www.example.com http:example.com")-以空格作为分隔符,而不是逗号。根据此列表是用空格分隔的。
  • 显然,逗号分隔的域和空格分隔的域都不起作用。与域列表匹配并将单个主机放在标头中仍然可以提高安全性,并且可以正常工作。回到@zerkms评论。看这里
  • 是的,它仍然抱怨多个标题。我觉得那将是理想的解决方案。我终于在今天早上弄清楚了。我想要的信息位于代码前面的http.request对象中。假设您有一个对象r * http.Request,则可以像以下原点一样获取原点:= r.Header.Get(" Origin");所以我只是在每个api调用上返回一个空对象(如果它不是正确的来源)。

我发现Origin信息在http.Request对象中。 你可以用

1
origin := r.Header.Get("Origin");

假设您有一个物体,例如

1
r *http.Request

如果对象来自example.com,则它将返回example.com,也将返回www.example.com。 然后,您可以测试它是否为这两个值之一,以进行身份验证。


Access-Control-Allow-Origin标头仅支持一个值,因此您必须检查Host请求标头,然后基于该标头做出决定:

1
2
3
4
5
6
7
8
9
10
package main

import"net/http"

func myHandler(w http.ResponseWriter, r *http.Request) {
    switch host := r.Header.Get("Host"); host {
    case"www.example.com","example.com":
            w.Header().Set("Access-Control-Allow-Origin","http://"+host)
    }
}

并不是说主机头有时会被代理服务器更改。 然后,他们通常会添加X-Forwarded-Host标头或类似标头。 但是,仅检查您是否信任代理(以及如何建立信任是一个不同的问题)。

  • 它的r.Header.Get(" Origin")不是主机
  • 这些标题有不同的用途。 有关主机头的说明,请参见RFC7230。
  • 我刚刚测试了它,Host返回了一个空字符串,origin返回了我要的内容,origin ...