自定义 http 标头破坏了 CORS

Posted

技术标签:

【中文标题】自定义 http 标头破坏了 CORS【英文标题】:Custom http Header breaks CORS 【发布时间】:2019-11-13 10:17:03 【问题描述】:

我的 API 具有以下 CORS 设置: (我是所有者,我可以更改这些设置) 中间件功能:

// HeaderMiddleware ...
func HeaderMiddleware(next httprouter.Handle) httprouter.Handle 
    return httprouter.Handle(func(w http.ResponseWriter, r *http.Request, p httprouter.Params) 
        w.Header().Set("Content-Type", "application/json")
        w.Header().Set("Access-Control-Allow-Origin", "*")
        w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-APIKEY")
        // ! Production
        // if r.Header.Get("X-APIKEY") != "fdfdsf5df6d541cd6" || r.RemoteAddr != frontendURL 
        //  w.WriteHeader(http.StatusForbidden)
        //  json.NewEncoder(w).Encode(NoContentResponseSuccess: false, Error: "You aren't allowed to request the api here.")
        //  return
        // 
        // ! Production

        next(w, r, p)
    )

X-APIKEY 标头还不是必需的,没有它的请求就可以正常工作:

fetch('http://localhost:8013/tobi@gmx.at/usage',  headers:   )
.then(response => response.json())
.then(console.log)

返回used: false(预期响应)

但是,如果我添加 X-APIKEY 标头:

fetch('http://localhost:8013/tobi@gmx.at/usage',  headers:  'X-APIKEY': 'sdfsdfsafsf'  )
.then(response => response.json())
.then(console.log)

抛出以下错误:Access to fetch at 'http://localhost:8013/tobiwibu@gmx.at/usage' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. 如果我在 Postman 中使用 X-APIKEY 标头发出请求,则表示 Access-Control-Allow-Origin 标头是随一起发送的: P.S.:我已经尝试过其他标题,它有效! 如果我使用 chrome(没有 X-APIKEY 标头)发出请求,则会发送 Access-Control-Allow-Origin 标头。 感谢您的帮助!

【问题讨论】:

似乎可能有一些应用程序逻辑查看X-APIKEY 并跳过基于该逻辑的响应设置Access-Control-Allow-Origin。没有看到相关代码,我们无法知道。 我刚刚添加了整个中间件功能。 100% 确定它被调用(在前后使用 print 进行测试)。我希望这就是你的意思。 添加自定义标头意味着浏览器在发送 GET 之前发出 OPTIONS 动词请求。您的服务器可能没有响应 OPTIONS。 【参考方案1】:

我现在已经这样修复它了: 我为我的 API-Token 滥用了 http Accept 标头。 示例:

fetch('http://10.0.0.11:8013/lopm@htl/usage',
"headers": "Accept": "fdfdsf5df6d541cd6++" )
.then(response => response.json())
.then(console.log)

当然,这不是一个非常好的解决方案,但它确实发挥了作用。 感谢大家给我有用的提示!

【讨论】:

以上是关于自定义 http 标头破坏了 CORS的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 spring mvc 和 $http 访问 CORS 环境中的自定义标头

由 CORS 阻止的 Spring Boot 自定义响应标头

自定义 HTTP 标头块 Jersey CORS 过滤器

带有 CORS 和自定义标头的 AngularJS

如何在 CORS 预检 OPTIONS 请求中发送自定义标头?

JQuery、CORS 和自定义响应标头