📄nginx跨域
2023-4-4
| 2023-4-10
0  |  0 分钟
type
status
date
slug
summary
tags
category
icon
password

1. 单个域名

nginx 配置参考:
location /xx { add_header Access-Control-Allow-Origin http://a.com; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; if ($request_method = 'OPTIONS') { return 204; } }

2. 多个域名

map尽量放在主配置文件里
map $http_origin $allow_origin { default ""; "~^(https?://localhost(:[0-9]+)?)$" $1; "~^(https?://127.0.0.1(:[0-9]+)?)$" $1; "~^(https?://172.10(.[\d]+){2}(:[0-9]+)?)$" $1; "~^(https?://192.168(.[\d]+){2}(:[0-9]+)?)$" $1; "~^(https?://.*.abc.com(:[0-9]+)?)" $1; "~^(https?://.*.geinino.com(:[0-9]+)?)" $1; } server { listen 11111; server_name localhost; location ~ /xxx { if ($request_method = 'OPTIONS') { return 204; } add_header Access-Control-Allow-Origin $allow_origin; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; #add_header Access-Control-Allow-Credentials是cookie配置,可不写,根据实际情况 add_header Access-Control-Allow-Credentials 'true'; proxy_pass http://1.2.3.4:5678; } }

3. 说明

3.1 Access-Control-Allow-Headers,防止下面的错误

Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
这个错误表示当前请求Content-Type的值不被支持。其实是我们发起了“application/json”的类型请求导致的。这里涉及到一个概念:预检请求(preflight request),请看下面“预检请求”的介绍。 ### 3.2 Access-Control-Allow-Method,防止出现以下错误
Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

3.3 给OPTIONS 添加 204的返回

  • 是为了处理在发送POST请求时Nginx依然拒绝访问的错误
  • 发送“预检请求”时,需要用到方法 OPTIONS ,所以服务器需要允许该方法

4. 补充

早期某个项目做安全测试时,发现尽管设置了$allow_origin,即orgin白名单,但是仍可以从非白名单的域名跨域请求。当时时间紧急,未深究根源,最后用逻辑判断规避。nginx 不支持常见的逻辑判断,可以用迂回策略:
# location模块配置 # 设置跨域配置 Start # 需配合nginx.conf的map $corsHost 使用,默认origin为空 set $flag 0; //这里的0很必要 if ( $http_origin != "" ) { //origin非空 set $flag "${flag}1"; } if ($corsHost = "" ) { //origin未匹配到map值 set $flag "${flag}2"; } if ($flag = "012") { //上面的条件是“且”的逻辑关系,即origin非空,且又不在白名单中,反馈404。 return 404; } #设置跨域配置 End
技术
  • 中间件
  • date获取GMT时间差Prometheus Operator的理解
    目录