报错如下:
同源策略(Same-Origin Policy, SOP)
同源策略(Same-Origin Policy,SOP)是Web浏览器中的一种关键安全机制,旨在限制不同源之间的交互,以保护用户数据的安全和隐私。
域名、协议、端口有一个不同就不是同源,三者均相同,这两个网站就是同源。
比如说:你在浏览器访问hellocode.fun这个网站,这个网站需要去访问abc.com的资源,在资源被返回回来时,就会被浏览器阻止。
这么做有以下好处:
- 防止跨站脚本攻击(XSS):SOP限制了一个网页脚本访问其他源的资源,减少了恶意脚本注入并窃取用户信息的风险。
- 防止跨站请求伪造(CSRF):通过限制跨源请求,SOP防止恶意网站利用用户的身份在其他网站上执行未授权的操作。
- 保护用户数据:SOP确保cookies和本地存储数据只能被创建它们的源访问,防止未经授权的访问。
但也不是所有资源都是要遵守同源策略的, MDN描述如下所示:
跨域资源共享(CORS)
尽管SOP提供了强有力的安全保障,但它也限制了合法的跨域资源共享需求。为了解决这些问题,Web标准引入了跨域资源共享(CORS)等机制,允许在特定条件下进行跨域交互。CORS是一个W3C标准,允许服务器声明哪些源可以访问其资源,突破了AJAX只能同源使用的限制。
CORS的工作原理
- 浏览器检测:当浏览器检测到AJAX请求跨域时,它会自动添加CORS相关的HTTP头信息。这些头信息用于告知服务器请求的源以及请求的性质。(简单请求与非简单请求有不同的HTTP头信息, 详细可见阮一峰的文章)
- 服务器响应:服务器需要通过设置适当的CORS响应头来允许跨域请求。常见的CORS响应头包括:
Access-Control-Allow-Origin
: 指定哪些源可以访问资源。Access-Control-Allow-Methods
: 指定允许的HTTP方法。Access-Control-Allow-Headers
: 指定允许的请求头。Access-Control-Allow-Credentials
: 指定是否允许发送凭据(如Cookies)。
- 浏览器处理:如果服务器响应中包含适当的CORS头信息,浏览器将允许跨域请求的响应被JavaScript访问,否则将被拦截。
不同服务器实现例子:
node.js直接配置
const http = require('http');
const port = process.env.PORT || 8000;
const server = http.createServer((request, response) => {
console.log(`METHOD: ${request.method}; URL: ${request.url}`);
// 设置CORS头信息
response.setHeader('Access-Control-Allow-Origin', '*'); // 允许所有源
response.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST, PUT, DELETE'); // 允许的HTTP方法
response.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); // 允许的请求头
if (request.method === 'OPTIONS') {
// 对于预检请求,直接返回成功响应
response.writeHead(204);
response.end();
return;
}
// 处理其他请求
response.writeHead(200, { 'Content-Type': 'application/json' });
response.end(JSON.stringify({ message: 'CORS is enabled for this server' }));
});
server.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Node.js(Express)
const express = require('express');
const cors = require('cors');
const app = express();
// 使用默认配置允许所有跨域请求
app.use(cors());
// 自定义配置
// app.use(cors({
// origin: 'http://example.com',
// methods: 'GET,POST',
// allowedHeaders: ['Content-Type', 'Authorization']
// }));
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Apache
在httpd.conf
或.htaccess
中添加:
<Directory "/var/www/html">
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET,POST,OPTIONS"
Header set Access-Control-Allow-Headers "Content-Type"
</Directory>
Nginx
在Nginx配置文件中添加:
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,Range';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
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,Range';
}