惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
About on SuperTechFans
WordPress大学
WordPress大学
雷峰网
雷峰网
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Latest news
Latest news
Spread Privacy
Spread Privacy
T
Threat Research - Cisco Blogs
T
Tor Project blog
博客园 - Franky
U
Unit 42
K
Kaspersky official blog
博客园_首页
G
GRAHAM CLULEY
美团技术团队
I
Intezer
T
The Exploit Database - CXSecurity.com
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
The Hacker News
The Hacker News
B
Blog
云风的 BLOG
云风的 BLOG
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
S
Securelist
Last Week in AI
Last Week in AI
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
M
MIT News - Artificial intelligence
Martin Fowler
Martin Fowler
Schneier on Security
Schneier on Security
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
SegmentFault 最新的问题
W
WeLiveSecurity
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
J
Java Code Geeks
Cyberwarzone
Cyberwarzone
爱范儿
爱范儿
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
The GitHub Blog
The GitHub Blog
S
Security @ Cisco Blogs
GbyAI
GbyAI
P
Proofpoint News Feed
D
Docker
D
DataBreaches.Net
aimingoo的专栏
aimingoo的专栏
博客园 - 司徒正美
T
Tenable Blog
V2EX - 技术
V2EX - 技术
The Register - Security
The Register - Security
V
Vulnerabilities – Threatpost
B
Blog RSS Feed

轶哥博客

blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog
blog
轶哥 · 2018-11-14 · via 轶哥博客

利用Nginx可以最简单且高效解决跨域问题。

跨域是前后端分离开发中非常常见的问题。这个问题网上已经有非常多的答案,但大部分是编程框架里面添加CORS头。但无论用什么Web框架,现已很难离开Nginx。因此直接在Nginx中处理跨域问题有得天独厚的优势,可以将OPTIONS请求拦截在API服务之前,节约服务器开销。

简单说,跨域分为简单跨域复杂跨域

简单跨域不会发送OPTIONS请求。

复杂跨域会发送一个预检查OPTIONS请求。

复杂跨域的条件是:

  1. 非GET、HEAD、POST请求。
  2. POST请求的Content-Type不是application/x-www-form-urlencoded, multipart/form-data, 或text/plain
  3. 添加了自定义header,例如Token

跨域请求浏览器会在Headers中添加Origin,通常情况下不允许用户修改其值。

配置示例

server {
        listen 80;
        server_name _;
        charset utf-8;
        location / {
                if ($http_origin ~ '^http(s)?://(localhost|www\.你的域名\.com)$') {
                        add_header 'Access-Control-Allow-Origin' "$http_origin" always;
                        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
                        add_header 'Access-Control-Allow-Headers' 'Accept, Authorization, Cache-Control, Content-Type, DNT, If-Modified-Since, Keep-Alive, Origin, User-Agent, X-Requested-With, Token, x-access-token' always;
                }

                if ($request_method = 'OPTIONS') {
                        add_header 'Access-Control-Allow-Origin' "$http_origin" always;
                        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
                        add_header 'Access-Control-Allow-Headers' 'Accept, Authorization, Cache-Control, Content-Type, DNT, If-Modified-Since, Keep-Alive, Origin, User-Agent, X-Requested-With, Token, x-access-token' always;
                        # Tell client that this pre-flight info is valid for 20 days
                        add_header 'Access-Control-Max-Age' 1728000;
                        add_header 'Content-Type' 'text/plain charset=utf-8';
                        add_header 'Content-Length' 0;
                        return 204;
                }

                proxy_http_version 1.1;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $host;
                proxy_set_header X-NginX-Proxy true;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_pass http://127.0.0.1:8080;
                proxy_redirect off;
        }
}

CRUL跨域测试

GET请求成功返回跨域头:

➜  ~ curl -I -H "Origin: http://localhost" http://localhost
HTTP/1.1 403 Forbidden
Server: nginx/1.15.6
Date: Wed, 14 Nov 2018 07:56:01 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 153
Connection: keep-alive
Access-Control-Allow-Origin: http://localhost
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Accept, Authorization, Cache-Control, Content-Type, DNT, If-Modified-Since, Keep-Alive, Origin, User-Agent, X-Requested-With, Token, x-access-token

OPTIONS预检请求成功返回跨域头:

➜  ~ curl -I -H "Origin: http://localhost" -X OPTIONS http://localhost
HTTP/1.1 204 No Content
Server: nginx/1.15.6
Date: Wed, 14 Nov 2018 08:19:36 GMT
Connection: keep-alive
Access-Control-Allow-Origin: http://localhost
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Accept, Authorization, Cache-Control, Content-Type, DNT, If-Modified-Since, Keep-Alive, Origin, User-Agent, X-Requested-With, Token, x-access-token
Access-Control-Max-Age: 1728000
Content-Type: text/plain charset=utf-8
Content-Length: 0