1. 为什么会跨域
跨域在我看来就是从自己的地盘去别人的地盘要资料,别人的资料你想拿就能拿的吗?(题外话,嘿嘿嘿)
浏览器有自己的一种安全机制叫做同源策略,这个是可以防止跨站脚本攻击!
什么是同源策略?
协议(http/https),域名/IP地址, 端口号一致的则是同源,代表着资源可以共享,如果任何其中一项不同即是不同源,那么此时资源就不会共享!
如果说前后端部署是放在同一个服务器下,那么就不会有跨域问题,但是现在大多数的项目都是前后端分离的项目,前端项目和后端接口域名是不一样的,那么前端访问后端接口的时候必然就会有跨域问题
2.如何解决跨域问题
1.服务器代理(项目中常用)
通过在vue-cli脚手架中配置proxy进行跨域处理,但是,vue-cli的跨域只能解决开发期间的跨域问题,项目上线跨域问题需要配置nginx
📢: 浏览器访问服务器的时候会存在跨域的问题,但是服务器之间不存在跨域问题
代理服务器的步骤:
- 客服端首先先向本地服务器发起请求
- 本地服务器作为代理,向目标服务器发送请求
- 目标服务器将数据返回到本地服务器
- 本地服务器将数据响应给客户端
//vue.config.js
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8080',//接口url地址
changeOrigin: true,//开启跨域
pathRewrite: { //重写
'^/api': '/api'
}
},
}
},
nginx代理 (简单)
在nginx服务器nginx.conf配置文件
server {
listen 8083;# 监听的端口
server_name localhost; #监听的主机名 也可以是域名或者ip地址
location ~ /api/ {
proxy_pass http://localhost:8084;
}
location ~ /prod/ {
proxy_pass http://localhost:8085;
}
}
2. CORS
CORS(Cross-Origin Resource Sharing,跨域资源共享)是一种跨域解决方案,它通过在 HTTP 头部添加特定的字段,来告诉浏览器是否允许跨域请求,他允许浏览器向跨源服务器发送
XMLHttpRequest请求,从而克服啦 AJAX 只能同源使用的限制,cors跨域分为简单请求和非简单请求的两种方式处理缺点: IE浏览器版本不能低于10
简单请求
- 使用 GET、HEAD、POST 方法中的任意一种。
- Content-Type 是 application/x-www-form-urlencoded、multipart/form-data、text/plain 中的任意一种。
- 请求中没有使用自定义的头部字段。
在浏览器发出请求后,浏览器判断是简单请求还是复杂请求,如果是简单请求
- 会自动在请求头部加上 Origin 字段,表示该请求来自哪个域。
- 如果服务器允许该域的跨域请求,就在响应头部加上 Access-Control-Allow-Origin 字段,表示允许该域的跨域请求
- 浏览器正确处理响应。如果服务器不加上Access-Control-Allow-Origin字段,浏览器将无法读取数据。
非简单请求
在浏览器发出请求后,浏览器判断是简单请求还是复杂请求,如果是复杂请求请求:
- 浏览器在发送跨域请求时,会先发送一个 OPTIONS 请求,该请求称为 Preflight Request。Preflight Request 的目的是向服务器确认当前跨域请求是否被允许。Preflight Request 请求头中会包含一个 Access-Control-Request-Method 字段,表示实际请求使用的 HTTP 方法。
- 服务器在接收到 Preflight Request 后,会检查请求头部中的 Origin 字段,判断当前跨域请求是否被允许。如果被允许,服务器会在响应头部中添加一些 CORS 相关的字段,如 Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers 等。
- 浏览器接收到服务器返回的响应后,会检查响应头部中的 CORS 相关字段是否符合要求,如果符合要求,就会发送实际的跨域请求。实际的跨域请求与普通请求一样,只不过在请求头部中多了一个 Origin 字段。
3.JSONP
面试的时候会说就行,项目上基本不咋用,那JSONP到底是怎么能解决跨域的呢?
利用的不是xhr请求, 利用的script标签的src可以跨域, 请求接口资源,同时携带callback回调函数名字, 将数据传给回调函数, 解决get不能解决post
//温馨提示 会被立即执行
functionn jsonp(url,callback){
const script= document.createElement('script') //生成一个script
script.src=url+'?callback='+callback //带着地址以及回调函数
document.body.appendChild(script) //塞进页面
}
function getData(data){}
jsonp("地址", getData)
优点:
- 兼容性很好 旧的浏览器也可以使用
缺点:
- 安全问题,返回的数据会被直接执行,可能会有XSS攻击等风险
- 只能支持get请求,不能使用Post等其他的请求方式
- 可读性差,比较难维护