JSON如何处理跨域请求:从原理到实践的全面指南
跨域请求的“拦路虎”:同源策略与JSON的关联性
在Web开发中,当我们通过前端JavaScript(如Fetch API、XMLHttpRequest)请求后端API时,经常会遇到一个报错:Access-Control-Allow-Origin,这就是浏览器同源策略(Same-Origin Policy)在“作祟”。
1 什么是同源策略?
同源策略是浏览器最核心的安全机制之一,它限制了一个源的文档或脚本如何与另一个源的资源进行交互,这里的“源”由协议(protocol)、域名(domain)、端口(port)三者共同决定,只要三者中有任何一个不同,就属于“跨域”(Cross-Origin)。
https://example.com(源A)请求https://api.example.com(源B,域名不同)→ 跨域http://example.com(源A)请求https://example.com(源B,协议不同)→ 跨域https://example.com:8080(源A)请求https://example.com:443(源B,端口不同)→ 跨域
2 JSON与跨域的“天然矛盾”
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,因其易于人阅读和编写,也易于机器解析和生成,成为前后端数据交互的主流格式,但问题在于:浏览器的同源策略默认禁止跨域请求获取响应数据,即使后端返回了JSON数据,前端也会因跨域限制而无法读取。
前端代码直接请求跨域JSON接口:
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('跨域失败:', error));
若后端未处理跨域,浏览器会直接抛出错误:
Access to fetch at 'https://api.example.com/data' from origin 'https://example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
跨域请求的核心解决方案:CORS机制
要解决JSON跨域请求问题,目前最主流、最标准的技术是跨域资源共享(Cross-Origin Resource Sharing, CORS),CORS通过HTTP头部,让服务器声明哪些外部源可以访问该资源,从而在保证安全的前提下实现跨域数据交互。
1 CORS的核心原理
CORS的本质是服务器端授权,当浏览器发起跨域请求时,会根据请求类型(简单请求/非简单请求)自动添加特定HTTP头部,服务器通过响应头中的Access-Control-Allow-*字段告知浏览器是否允许该跨域请求。
(1)简单请求(Simple Request)
满足以下两个条件的请求属于“简单请求”:
- 请求方法为
GET、POST或HEAD; - 请求头仅限
Accept、Accept-Language、Content-Language、Content-Type(且值为application/x-www-form-urlencoded、multipart/form-data或text/plain)。
流程:
- 浏览器直接发起跨域请求,自动添加
Origin头部(如Origin: https://example.com); - 服务器检查
Origin,若允许跨域,在响应中添加Access-Control-Allow-Origin头部(值为或允许的源,如https://example.com); - 浏览器收到响应,若包含
Access-Control-Allow-Origin,则允许前端读取响应数据;否则,拒绝并抛出错误。
示例响应:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Content-Type: application/json
{"name": "JSON数据", "value": 123}
(2)非简单请求(Non-Simple Request)
不满足“简单请求”条件的请求(如PUT、DELETE方法,或请求头包含Authorization、Content-Type: application/json等)属于“非简单请求”,这类请求会先发送一个预检请求(Preflight Request),使用OPTIONS方法询问服务器是否允许实际请求。
预检请求(OPTIONS):
OPTIONS /data HTTP/1.1 Origin: https://example.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: Content-Type, Authorization Host: api.example.com
服务器预检响应:
若服务器允许该请求,需返回以下头部:
HTTP/1.1 204 No Content Access-Control-Allow-Origin: https://example.com Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Headers: Content-Type, Authorization Access-Control-Max-Age: 86400 // 预检结果缓存时间(秒)
实际请求:
预检通过后,浏览器才会发送真正的跨域请求(如PUT /data),后续流程与简单请求一致。
2 CORS响应头关键参数说明
| 头部字段 | 作用 | 示例 |
|---|---|---|
Access-Control-Allow-Origin |
指定允许的跨域源,表示允许所有源 | Access-Control-Allow-Origin: * |
Access-Control-Allow-Methods |
指允许的请求方法(多个用逗号分隔) | Access-Control-Allow-Methods: GET, POST, PUT |
Access-Control-Allow-Headers |
指允许的请求头(多个用逗号分隔) | Access-Control-Allow-Headers: Content-Type, Authorization |
Access-Control-Allow-Credentials |
是否允许发送Cookie/认证信息(需配合前端credentials: 'include') |
Access-Control-Allow-Credentials: true |
Access-Control-Max-Age |
预检请求结果的缓存时间,减少重复预检 | Access-Control-Max-Age: 86400 |
后端如何实现CORS支持?
要让服务器支持CORS,核心是在响应中添加正确的CORS头部,以下是常见后端语言的实现示例:
1 Node.js (Express框架)
使用cors中间件是最简单的方式:
npm install cors
const express = require('express');
const cors = require('cors');
const app = express();
// 允许所有源(生产环境建议指定具体源)
app.use(cors());
// 或配置允许特定源、方法、头
app.use(cors({
origin: 'https://example.com',
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true // 允许携带Cookie
}));
app.get('/data', (req, res) => {
res.json({ name: 'Node.js + CORS' });
});
app.listen(3000, () => console.log('Server running on port 3000'));
2 Python (Flask框架)
使用flask-cors扩展:
pip install flask-cors
from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
# 允许所有源
CORS(app)
# 或配置特定源
CORS(app, resources={
r"/data": {
"origins": ["https://example.com"],
"methods": ["GET", "POST"],
"allow_headers": ["Content-Type"]
}
})
@app.route('/data')
def get_data():
return jsonify({"name": "Flask + CORS"})
if __name__ == '__main__':
app.run(debug=True)
3 Java (Spring Boot)
通过@CrossOrigin注解或全局配置:
@RestController
@RequestMapping("/data")
@CrossOrigin(origins = "https://example.com", methods = {RequestMethod.GET, RequestMethod.POST})
public class DataController {
@GetMapping
public ResponseEntity<String> getData() {
return ResponseEntity.ok("{\"name\": \"Spring Boot + CORS\"}");
}
}
或全局配置(推荐):
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("https://example.com")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}
4 Nginx反向代理配置
若后端服务无法直接修改代码(如传统Java应用),可通过Nginx配置CORS:
server {
listen 80;
server_name api.example.com;
location / {
# 允许所有源(生产环境替换为具体源)
add_header 'Access-Control-Allow-Origin' '*';
add_header '


还没有评论,来说两句吧...