什么是同源?
所谓同源是指:域名、协议、端口 相同。
为什么指定同源策略?
同源策略(Same origin policy)存在于浏览器端是一种约定,由Netscape(网景)提出,用来保护浏览器的数据安全。如果没有同源策略,A网站可以随意访问B网站的Cookie等信息是不安全的,现在所有支持JavaScript 的浏览器都会使用这个策略。
同源策略有什么影响,哪些需要跨域操作?
- 调用XMLHttpRequest有时候需要跨域,同源策略是禁止使用 XHR 对象向不同源的服务器地址发起 HTTP 请求。
- fetchAPI通过跨站点方式访问资源,网络字体,例如Bootstrap(通过CSS使用@font-face 跨域调用字体)。
- 通过canvas标签,绘制图表和视频。
- DOM操作,同源策略禁止对不同源页面 DOM 进行操作。这里主要场景是 iframe 跨域的情况,不同域名的 iframe 是限制互相访问的。
如下表给出了相对http://
www.example.com/demo/page.html
的同源对比示例:
URL | 是否同源 | 原因 |
---|---|---|
http://www.example.com/demo01/other.html | 是 | 协议、域名、端口相同 |
http://www.example.com/demo/inner/another.html | 是 | 协议、域名、端口相同 |
https:// www.example.com/secure.html | 否 | 协议不同(https ) |
http://www.example.com:81 /demo/etc.html | 否 | 端口 不同 |
http://news.example.com /demo/other.html | 否 | 域名 不同 |
什么是跨域?
1 当浏览器中一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。
2 用户在使用浏览器的情况下会使用到 CORS,因为控制访问权限的是浏览器而非服务器。因此使用其它客户端的时候无需关心任何跨域问题。
3 同源策略(Same Origin Policy)是一种约定,它是浏览器最核心也是最基本的安全功能
如何解决跨域?
1 代理配置
以/api
为根目录为例
请求跨域接口的时候加上要跨域的接口地址即可
export function signIn() {
return http.get("/api/singIn")
}
1-1 webpack代理配置
具体配置方法参考如下:(可参考devServer.server)
Vue
脚手架创建的项目在vue.config.js
文件配置以下代理(加上logLevel:'debug',
查看代理实际情况)webpack
手动搭建的项目在webpack.config.js
文件配置以下代理(由于不同人搭建方式不一样,如可能在webpack.dev.conf.js
配置,或者对于所抽离的文件)
devServer:{
proxy:{
'/api': {
// 需代理地址
target: 'https://example.com/',
host: '0.0.0.0',
port: port,
// https: true, // 允许https接口代理
// hotOnly: true, // 热更新
// 如果是代理到域名,需要设置changeOrigin: true
changeOrigin: true
// 路径重写(代理重写)
// 如果实际接口没有当前path则需重写路径,且使用调用接口的时候需要加上当前path
// 比如访问的API路径:/api/singIn,设置pathRewrite: {’^/api’ : ‘’},后,最终代理访问的路径:https://example.com/singIn
pathRewrite:{
'^/api':''
}
},
},
}
webpack
低版本代理配置方式
dev:{
proxyTable:{
'/api': {
// 需代理地址
target: 'https://example.com/',
// 如果是代理到域名,需要设置changeOrigin: true
// 路径重写(代理重写)
// 如果实际接口没有当前path则需重写路径,且使用调用接口的时候需要加上当前path
// 比如访问的API路径:/api/singIn,设置pathRewrite: {’^/api’ : ‘’},后,最终代理访问的路径:https://example.com/singIn
pathRewrite:{
'^/api':''
}
},
},
}
1-2 nginx代理配置
下载nginx包
在nginx.conf文件内配置
location /api {
rewrite ^/api/?(.*)$ /$1 break;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 允许cros跨域访问
# add_header 'Access-Control-Allow-Origin' '*';
proxy_pass http://0.0.0.0:8080/; # 转发地址
}
2,在服务端设置请求头,一般都是用于项目测试阶段。
CORS(Cross-Origin Resource Sharing,跨域资源共享)方案
'Access-Control-Allow-Credentials': 'true', // 后端允许发送Cookie
'Access-Control-Allow-Origin': '*', // 允许访问的域(协议+域名+端口)
'Access-Control-Allow-Methods': "POST,GET,DELETE,PUT,OPTIONS" // 允许请求方式用着五种`
var http = require('http');
http.createServer(function(request, response) {
response.writeHead(200, {
'Access-Control-Allow-Credentials': 'true', // 后端允许发送Cookie
'Access-Control-Allow-Origin': '*', // 允许访问的域(协议+域名+端口)(*代表允许全部访问)
'Access-Control-Allow-Methods': "POST,GET,DELETE,PUT,OPTIONS" // 允许请求方式用着五种
})
if (request.url == "/getData") {
const data = {
status: "ok",
data: [{
name: '三妹',
age: 10
}
]
}
response.end(JSON.stringify(data))
}
}).listen(8081,function(){
console.log("服务启动成功");
});
这种方法虽然简单,但是这种方法是h5新出的,所以这种方法有兼容性问题
3,JSONP格式
jsonp 是客户端跨源获取服务器数据的通信常用方法。
由于DOM中的src属性支持跨域,所以JSONP的原理也就是利用了script标签中的src来实现跨域的,除了script标签之外,还有img和link标签.
<!--不受同源策略限制的标签-->
<img src="http://www.api.com/1.jpg" alt="">
<link rel="stylesheet" href="http://www.api.com/1.css">
<script src="http://www.api.com/1.js"></script>
JSONP实现原理
- 1)利用了script的src属性支持跨域访问
- 2)script标签的后面需要写上需要请求的页面,发送了一个方法的名字到服务器.
- 3)服务器接收到名字之后,拼接一个方法的调用在参数中传入需要给浏览器的数据
- 4)返回浏览器,浏览器把他们当js解析,没有跨域问题,从服务器获取数据
JSONP的缺点
- 1它只支持GET请求而不支持POST等其它类型的HTTP请求
- 2它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
- 3 jsonp在调用失败的时候不会返回各种HTTP状态码。
- 4缺点是安全性。万一假如提供jsonp的服务存在页面注入漏洞,即它返回的javascript的内容被人控制的。那么结果是什么?所有调用这个 jsonp的网站都会存在漏洞。于是无法把危险控制在一个域名下…所以在使用jsonp的时候必须要保证使用的jsonp服务必须是安全可信的。
原生js使用JSONP
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function getData(data){
document.write(JSON.stringify(data))
}
</script>
<script src="http://localhost:3000/jsonp/jsonp?callback=getData"></script>
</body>
</html>
jQuery使用JSONP
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP 实例</title>
<script src="https://cdn.static.runoob.com/libs/jquery/1.8.3/jquery.js"></script>
</head>
<body>
<div id="divCustomers"></div>
<script>
// 直接只用$.getJSON调用
$.getJSON("http://localhost:3000/jsonp/jsonp?callback=?", function (data) {
document.write(JSON.stringify(data))
});
// or
// 使用ajax,dataType设置为jsonp调用
$.ajax({
type : "GET",
dataType : "jsonp",
url : "http://localhost:3000/jsonp/jsonp",
success : function(data){
document.write(JSON.stringify(data))
console.log('data', data)
}
})
</script>
</body>
</html>
总结:本人才疏学浅,水平有限,请大家多多包涵和指点。加油🤝🫡🫶