导读:本期聚焦于小师妹创作的《浏览器跨域被拦截怎么办?一文搞懂CORS响应头与代理配置方案》,敬请观看详情。页面里发请求被浏览器控制台报出CORS policy错误,资源加载被直接拦截,这是前后端分离架构下最常见的困扰之一。本文从浏览器同源策略的拦截机制讲起,说明为什么跨域请求会被拦截、预检OPTIONS请求何时触发,然后详细拆解服务端需要返回的Access-Control-Allow-Origin、Access-Control-Allow-Headers等关键响应头的含义与配置方式,分别给出Nginx、Node.js、Java Spring等后端的配置示例。对于无法修改服务端代码的场景,再介绍开发环境与生产环境的前端代理方案,分析代理跨域的原理与注意事项,帮助你彻底解决跨域问题。

同源策略是浏览器最重要的安全机制之一,它规定页面中的脚本只能读取与当前页面同协议、同域名、同端口下的资源。一旦前端页面向不同源的服务端发起请求,浏览器就会对响应进行检查,缺少必要的CORS响应头时直接拦截,控制台通常会报出类似Access to XMLHttpRequest has been blocked by CORS policy的错误。要彻底解决这个问题,可以从两个方向入手:一是让服务端正确返回CORS响应头,二是通过代理让请求变成同源。本文分别展开讲解。

浏览器跨域被拦截怎么办?一文搞懂CORS响应头与代理配置方案

为什么浏览器要拦截跨域请求

首先要明确一点:跨域请求大多数情况下其实已经到达了服务端,服务端也正常返回了数据,拦截发生在浏览器端。浏览器拿到响应后会检查其中的CORS响应头,如果不满足要求,就会拒绝把响应交给页面脚本,这就是为什么有时你在服务端日志里能看到请求成功,而前端却报错的原因。

同源策略的初衷是保护用户安全。想象一下,如果你登录了银行网站,浏览器保存了Cookie,此时又访问了一个恶意网站,如果没有同源策略,恶意网站的脚本就能携带你的Cookie向银行发起请求并读取响应,用户的资产信息将被随意窃取。同源策略正是通过限制脚本的跨源读取能力来堵住这个漏洞。

跨域请求分为简单请求和预检请求两类。简单请求要求请求方法为GET、POST或HEAD,且请求头只包含AcceptAccept-LanguageContent-Type(仅限application/x-www-form-urlencoded、multipart/form-data、text/plain)等安全字段。一旦不满足这些条件,比如使用了Content-Type: application/json、请求方法为PUT或DELETE、或者携带了自定义token头,浏览器就会先发送一个OPTIONS方式的预检请求,询问服务端是否允许真正的请求。很多人配置了CORS却仍然失败,问题往往出在预检请求没有被正确处理。

服务端配置CORS响应头

CORS的核心是几个响应头。Access-Control-Allow-Origin指定允许访问的源,值可以是具体的协议加域名加端口,也可以是星号表示允许所有源,但注意与携带Cookie一起使用时不能为星号。Access-Control-Allow-Methods声明允许的HTTP方法,Access-Control-Allow-Headers声明允许的请求头,预检请求通过后服务端必须返回这两项。Access-Control-Allow-Credentials设为true时,浏览器才允许请求携带Cookie。Access-Control-Max-Age可以设置预检结果的缓存时间,减少不必要的OPTIONS请求。

以Nginx为例,一个典型的配置如下:

location /api/ {
    add_header Access-Control-Allow-Origin $http_origin always;
    add_header Access-Control-Allow-Credentials true always;
    add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
    add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Token" always;
    # 预检请求直接返回,不转发到后端
    if ($request_method = OPTIONS) {
        return 204;
    }
    proxy_pass http://127.0.0.1:8080/;
}

注意配置中的always参数,它保证错误响应(如404、500)也会带上CORS头。如果不加,正常请求看起来跨域没问题,一旦接口报错,浏览器又会抛出CORS异常,让开发者误判问题根源。

在Node.js的Express框架中,可以使用cors中间件快速处理:

const express = require('express');
const cors = require('cors');
const app = express();

// 允许指定来源携带Cookie访问
app.use(cors({
    origin: 'https://www.ipipp.com',
    credentials: true,
    maxAge: 86400
}));

app.listen(3000, () => console.log('服务已启动'));

在Java Spring项目中,则可以通过全局配置类实现:

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
                .allowedOriginPatterns("https://*.ipipp.com")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(true)
                .maxAge(3600);
    }
}

无论哪种语言,配置思路都是一致的:对预检的OPTIONS请求返回204状态码并附带全部许可头,对实际请求的响应附加Access-Control-Allow-Origin等头信息。排查问题时,用浏览器开发者工具的Network面板查看OPTIONS请求的响应头,基本能定位到缺少哪一项配置。

代理方案:绕过跨域限制

如果服务端不在你的控制范围内,比如调用第三方接口,无法修改其响应头,代理就是更合适的方案。代理的原理很直接:让前端请求发给与自己同源的代理服务器,代理服务器在服务端转发请求给目标接口。由于服务端之间通信不受同源策略约束(同源策略只限制浏览器),跨域问题自然不存在。

开发环境下,前端构建工具普遍内置了代理支持。以Vite为例,在配置文件中这样写:

export default {
    server: {
        proxy: {
            '/api': {
                target: 'https://target.ipipp.com',
                changeOrigin: true,
                rewrite: (path) => path.replace(/^\/api/, '')
            }
        }
    }
}

这样页面中的请求只需写相对路径/api/user,与页面同源,浏览器不会拦截。Webpack对应的devServer.proxy配置方式几乎相同,Vue CLI创建的项目也可以在配置文件中做同样设置。

生产环境没有构建工具的devServer,一般用Nginx承担代理角色:

server {
    listen 80;
    location / {
        root /var/www/dist;   # 前端静态文件
        try_files $uri $uri/ /index.html;
    }
    location /api/ {
        proxy_set_header Host $http_host;
        proxy_pass https://target.ipipp.com/;
    }
}

这种把前端静态资源和接口代理统一在同一个域名下的部署方式,本质上让所有请求都变成了同源请求,是生产环境最稳妥的做法。

使用代理时要注意两点:一是代理转发可能丢失或改写Host头和Cookie,必要时通过proxy_set_header显式传递;二是开发环境代理只在本地生效,不要以为配置了devServer就万事大吉,上线部署仍需Nginx等网关层的配合。把服务端CORS头和代理方案结合理解,跨域问题就再也没有神秘感了。

跨域CORS前端代理修改时间:2026-09-02 03:30:41

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。