目录
同源策略(浏览器控制)
定义
思考:
跨域的N种方法
Jsonp
跨域资源共用(CORS)
预检(OPTIONS请求)
代理服务(优先考虑)
实战CORS(Fetch+node.js)
小结
同源策略(浏览器控制)
定义
禁止一个源(origin)的脚本&文档和另一个源的脚本&文档交互
- 两个URL的protocol,port和host相同,那么同源
- 思考:如果两个源产生过多交互会有什么问题?
思考:
- 为什么不禁用不同源的js?(引用组件,引用cdn,所以禁用是不现实的)
- 应不应该允许不同源的js修改dom?(允许,CDN上的js改变dom是正常行为)
- 应不应该允许不同源的js获取远程图片内容?(不允许,不允许远程执行代码)
- 应不应该允许网站提交数据到不同源的服务器?(不允许,需要同源策略管控,如它收集你的数据,提交给自己服务器了)
- 应不应该允许网站提交cookie到不同源的服务器?(不允许,除非配置跨域)
跨域的N种方法
确定2个源之间是安全的 可以采用跨域(绕过同源策略)
Jsonp
- 利用不限制跨域脚本执行的特点
// 服务端数据(data.js)
jsonp('example', {
a: 1,
b: 2
})
// index.html 样板代码
function jsonp(topic, data) {
console.log(topic, data)
}
// 加载跨域数据脚本
var script = document.createElement('script')
script.setAttribute('src', 'data.js')
document.getElementsByTagName('head')[0].appendChild(script)
思考:
- Jsonp可以用来提交数据吗?(本质上讲是一个script标签发送的get请求,可以提交数据,在路径里拼接,在url的query上,可以提交,但是是不合适的)
- 尝试为fetch函数扩展jsonp功能
// 扩展代码,实现后的调用
fetch(<jsonp-url>,{method: 'jsonp'})
.then(data => {
console.log(data)
})
跨域资源共用(CORS)
跨域资源共用(Cross-Origin Resource Sharing)使用额外HTTP头允许指定的源和另一个源进行交互
预检(OPTIONS请求)
也是一次请求,消耗带宽,消耗延迟
代理服务(优先考虑)
利用代理将不同源的资源代理到同源的资源
Proxy(node代理)
具体策略以网络为准,看哪个策略最优
实战CORS(Fetch+node.js)
- 观察node.js在服务端实现CORS跨域
- 观察浏览器中fetch的使用方法
- 观察OPTIONS预检请求
// node服务
const express = require('express')
// 页面1
const app1 = express()
app1.get('/', (req, res) => {
res.send("hello")
})
app1.listen(3000)
// 页面2
const app2 = express()
app2.options('/api', (req, res) => {
// 其他源的网站可以跨域访问
res.set('Access-Control-Allow-Origin' , "*")
// 请求头加token
res.set('Access-Control-Allow-Headers', "content-type,token")
// POST/GET/HEAD 是简单请求,而PUT/DELETE需要授权
res.set('Access-Control-Allow-Methods', "PUT")
res.sendStatus(200)
})
app2.get('/api', (req, res) => {
res.set('Access-Control-Allow-Origin', '*')
res.send('go-to')
})
app2.post('/api', (req, res) => {
// res.set('Access-Control-Allow-Origin', 'http://www.dev.com')
res.send('go-to')
})
app2.put('/api', (req, res) => {
res.set('Access-Control-Allow-Origin', 'http://www.dev.com')
res.send('go')
})
app2.listen(3001)
子域名之间也是跨域的
父子域名之间也是跨域的
fetch('http://dev.com/api,{mode:'no-cors'})
// 200 通了,但是透明请求不返回数据,还是被同源策略管制
小结
- 理解跨域要解决的问题而不是记住跨域这个现象和处理方法
- 子域名和父域名交互的时候因为子域名可以修改自己的域为父域名可以解决跨域问题
- 理解策略要解决的问题,而不是记住处理方法
- 决定用哪种策略核心的原则是在安全性前提下获得最优效率