前端解决跨域问题
1. 为什么会出现跨域问题
浏览器的同源策略
- 浏览器规定非同源网站不能相互发送ajax请求
- 假设A、B网站不同源,A向B发送ajax请求,其实请求时发送过去了,只不过浏览器拒绝了B发送过来的响应,然后报错
- 同源:网站拥有相同的:协议、端口号、域名,三者有一个不一样就不是同源
2. 解决办法
JSONP
JSONP
只支持
GET
方法
-
利用
script
标签的
src
属性-
src
有发送请求的功能且不是同源策略的影响 -
将非同源服务器端请求的地址写在
src
属性上
<script src="http://www.baidu.com"></script>
- 请求地址必须返回合法的JS代码
-
-
服务器端传过来的响应数据必须以函数的形式,要传给客户端的数据作为函数的参数
app.get('/first',(req,res)=>{ const result = 'fn({name:"张三",age: 10})'; res.send(result); })
-
在客户端定义函数
fn
<script> function fn(data){ console.log(data); } </script> <script src="http://localhost:3000/first"></script>
-
服务器端响应过来的是一个字符串但是会被
script
标签解析为js代码<script> fn({name:"张三",age:10}) </script>
-
这就相当于在另一个
script
标签中调用了第一个
script
里面的函数
fn()
CORS
-
origin
:协议+主机+端口 -
添加头部
Access-Control-Allow-Origin
到响应里 -
以
nodejs
构建的后端服务器为例-
引入
cors
并使用
const express = require('express'); const app = express(); const cors = require('cors'); // 使用并配置 app.use( cors({ origin:"*", // * 表示允许所有源访问 methods:['GET','POST'], // 配置允许使用的方法 }) )
-
引入
服务器代理
在vue中修改
config
文件夹下的
index.js
文件
proxyTable: {
'/api': { //请求前缀,加上代表走代理,不加不走
target: 'https://188.188.18.8', // 代理目标的基础路径
//用于控制请求头中的host值,默认true,
//为true时,服务器收到请求头中的host为:localhost:5000,
//为false时,服务器收到请求头中的host为:localhost:8080,
changeOrigin: true,
pathRewrite: {
'^/api': '' //'^/api'(正则表达式)表示匹配所有以'/api'开头的接口
}
},
// 可以设置多个代理
'/foo': {
}
}
-
调用实例
this.$http.get('/api/v4/user/login', [options]).then(function(response){ // 响应成功回调 }, function(response){ // 响应错误回调 });
-
配置原理:有跨域问题是因为浏览器的同源策略,跨域问题只存在于浏览器,服务端不存在跨域问题,所以只需要把http请求由浏览器端发起修改为由本地服务器代理发起,就能解决跨域问题
- 未设置代理时的通信原理: 本地文件 – 浏览器 – 远程服务端
- 设置了代理时的通信原理: 本地文件 – 浏览器 – 本地服务端 – 远程服务端
-
通过浏览器打开页面,当我们通过ajax发起请求时:
本地服务端的地址(通常是localhost:8080或者127.0.0.1:8080)会先一步收到这个请求,本地服务端会对这个请求的地址字符串进行一次分析。
如果地址字符串前面部分是/api,那么本地服务器会将api接口的字符串进行一次替换,变为 https://188.188.18.8/v4/ (配置地址) + user/login(接口调用方法处的详细地址),目标地址(https://188.188.18.8/v4/)。向当前服务器上的文件发起请求,去获取服务器上其他东西,自然就不是跨域了。