一篇文章让你彻底搞懂什么是跨域

跨域(CORS)深入分析

1. 什么是跨域?

跨域(Cross-Origin)是指浏览器执行的某些请求时,当前网页的源(Origin)与请求资源的不一致。例如:

  • 同源(不会跨域)
    • http://example.com/page.html 访问 http://example.com/data.json
  • 跨域(浏览器限制)
    • http://example.com 访问 http://api.example.com
    • http://localhost:3000 访问 http://localhost:5000
    • http://example.com:80 访问 http://example.com:8080

2. 浏览器如何访问服务器?

当你在浏览器中打开 http://example.com,浏览器会向 example.com 服务器发起一个 HTTP 请求,服务器返回 HTML、CSS、JavaScript 等资源,然后浏览器解析和渲染网页。

3. 网页如何访问另一个服务器?

网页本身并不是服务器,它是浏览器渲染的内容,但网页中的 JavaScript 代码可以发起 HTTP 请求。例如,一个网页可能会使用 fetch()XMLHttpRequest 请求 API 获取数据:

fetch("http://api.example.com/data")
  .then(response => response.json())
  .then(data => console.log(data));

这时,浏览器会尝试从 http://api.example.com 获取数据。但如果这个 API 服务器与网页来源 (http://example.com) 不同,就会触发同源策略,默认情况下浏览器会拦截请求。

4. 为什么浏览器会拦截?

同源策略(Same-Origin Policy, SOP) 是浏览器的安全机制,防止恶意网站随意读取你在其他网站上的数据。例如,如果没有同源限制,一个黑客网站 http://malicious.com 可能会使用 JavaScript 访问你的银行账户 API http://bank.com/api,并获取你的个人数据。

4.1 影响的操作

  • XMLHttpRequest / Fetch 请求(被拦截)
  • WebSocket(部分受限)
  • DOM 访问(受限,如 iframe
  • Cookie、LocalStorage、IndexedDB 访问(受限)

但以下情况不会被拦截:

  • <script><img><link><iframe>
  • JSONP 方式
  • CORS 允许的请求

5. 服务器如何允许跨域访问?

如果 http://api.example.com 服务器希望 http://example.com 可以访问它,需要在响应头中加上 Access-Control-Allow-Origin,例如:

Access-Control-Allow-Origin: http://example.com

这样,浏览器才会放行这次请求。

5.1 浏览器如何获取 Access-Control-Allow-Origin

浏览器在处理跨域请求时,首先会发送一个请求,其中包含 Origin 头,该头表示发起请求的源。例如:

GET /data HTTP/1.1
Host: api.example.com
Origin: http://example.com

服务器接收到请求后,会检查 Origin 头是否在允许的域列表中。如果允许跨域访问,服务器会在响应中返回 Access-Control-Allow-Origin 头,例如:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json

当浏览器接收到这个响应并看到 Access-Control-Allow-Origin 头包含了请求的 Origin 值,它就会放行该请求,允许 JavaScript 访问返回的数据。

如果 Access-Control-Allow-Origin 头缺失或不匹配 Origin,浏览器就会阻止 JavaScript 访问响应内容,并在控制台报跨域错误。

6. CORS(跨域资源共享)

CORS(Cross-Origin Resource Sharing)是一种允许跨域访问的机制。浏览器通过HTTP 响应头来决定是否允许跨域访问。

6.1 CORS 主要响应头

Header作用
Access-Control-Allow-Origin指定允许的域,如 * 代表所有域
Access-Control-Allow-Methods允许的 HTTP 方法(如 GET, POST
Access-Control-Allow-Headers允许的请求头
Access-Control-Allow-Credentials是否允许携带 Cookie
Access-Control-Expose-Headers允许前端访问的额外响应头

6.2 CORS 请求类型

1. 简单请求

只包含:

  • GET, POST, HEAD 方法
  • 不包含自定义头部(Content-Type 限于 text/plain, multipart/form-data, application/x-www-form-urlencoded

请求示例:

GET /api/data HTTP/1.1
Origin: http://example.com

服务器响应:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
2. 预检请求(Preflight)
  • 当请求方法是 PUT/DELETE 或包含自定义头部时,浏览器会先发送 OPTIONS 请求
  • 服务器需要响应允许的方法和头部

请求示例(浏览器自动发送的 OPTIONS 请求):

OPTIONS /api/update HTTP/1.1
Origin: http://example.com
Access-Control-Request-Method: PUT

服务器响应:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization

7. 解决跨域问题的方案

7.1 服务器端开启 CORS

Spring Boot 配置 CORS
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig {
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedOrigins("http://example.com")
                        .allowedMethods("GET", "POST", "PUT", "DELETE")
                        .allowedHeaders("*")
                        .allowCredentials(true);
            }
        };
    }
}

7.2 代理服务器(Nginx 反向代理)

在 Nginx 配置文件中添加:

server {
    location /api/ {
        proxy_pass http://backend-service;
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    }
}

7.3 JSONP(仅适用于 GET 请求)

前端示例:

<script src="http://example.com/api?callback=handleResponse"></script>
<script>
    function handleResponse(data) {
        console.log(data);
    }
</script>

8. 总结

  • 同源策略 限制了跨域请求。
  • CORS 通过 HTTP 头允许跨域访问。
  • 预检请求 适用于复杂请求(如 PUT、自定义头)。
  • 服务器配置 CORS 或使用代理 可以解决跨域问题。
  • JSONP 是一种仅限 GET 请求的跨域方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值