nginx跨域实战:解决openresty环境下跨域脚本冲突

在 OpenResty 环境中,Nginx 本身不执行 JavaScript,所谓“跨域脚本冲突”实际是前端浏览器因 CORS 策略 阻止了对 Nginx 后端接口的请求,而问题常被误归因为“Nginx 运行了脚本”。真正要解决的,是让 Nginx(通过 OpenResty 的 Lua 模块或纯配置)正确响应浏览器的跨域预检(OPTIONS)和携带 CORS 头的主请求。

明确跨域发生的位置和责任方

跨域限制由浏览器强制执行,服务端(Nginx)无权“绕过”,只能主动配合:提供合法的 Access-Control-Allow-Origin、Access-Control-Allow-Methods 等响应头,并正确处理 OPTIONS 预检请求。OpenResty 的优势在于可用 Lua 精确控制这些行为,但多数场景下纯 Nginx 配置已足够。

基础 CORS 配置(推荐优先使用)

在 server 或 location 块中添加标准 CORS 响应头,适用于简单跨域(如前端域名固定、无需 Cookie):

允许指定源:add_header Access-Control-Allow-Origin "https://your-frontend.com"; 允许方法:add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; 允许携带凭证(如 Cookie)时必须显式指定源,不能用 *:add_header Access-Control-Allow-Credentials "true"; 暴露自定义响应头(如 Authorization):add_header Access-Control-Expose-Headers "Authorization";

正确处理 OPTIONS 预检请求

浏览器在发送复杂请求(如带 Content-Type: application/json 或自定义 header)前,会先发一个 OPTIONS 请求。Nginx 必须返回 204(无内容)并带上 CORS 头,否则预检失败,后续请求被拦截:

在对应 location 中添加:if ($request_method = ‘OPTIONS’) { add_header Access-Control-Allow-Origin "*"; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization"; add_header Access-Control-Max-Age 1728000; add_header Content-Type ‘text/plain; charset=utf-8’; add_header Content-Length 0; return 204; } 注意:不要在 if 块外重复 add_header,避免响应头叠加;若用 OpenResty,也可用 access_by_lua_block 统一拦截 OPTIONS,逻辑更清晰。

OpenResty 中用 Lua 动态控制 CORS(进阶场景)

当需根据请求头、来源域名白名单或路径动态放行时,Lua 更灵活。例如只允许特定子域名跨域:

在 location 中启用 Lua:access_by_lua_block { local origin = ngx.req.get_headers()["Origin"] if origin and (string.match(origin, "^https://app%.mycompany%.com$") or string.match(origin, "^https://dev%.mycompany%.com$")) then ngx.header["Access-Control-Allow-Origin"] = origin ngx.header["Access-Control-Allow-Credentials"] = "true" ngx.header["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS" ngx.header["Access-Control-Allow-Headers"] = "Content-Type, Authorization" if ngx.var.request_method == "OPTIONS" then ngx.header["Access-Control-Max-Age"] = "86400" ngx.status = 204 ngx.exit(204) end end } 关键点:Lua 中设置 header 必须在 ngx.exit 前完成;OPTIONS 请求必须显式 ngx.exit(204),不可依赖 Nginx 默认流程。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。