问题场景:使用uniapp框架开发h5页面调用后端接口(线上开发服务器环境下),出现跨域问题。
- 前端请求配置说明:前端使用uniapp编写h5代码,前端使用promise异步函数对uniapp自带请求进行二次封装,服务器请求路径使用baseUrl公用配置路径。调用接口时,接口预检正常返回,数据返回时提示跨域
本次使用的解决方案:
-
由后端在header头添加origin语句,放开指定域名或所有域名,前端不做改动,放开后前端再发送请求时,接口数据正常返回。
-
前端使用 HBuilder X 开发工具内置浏览器访问没有跨域问题,需要安装相应插件,安装步骤如下:
安装完重启开发者工具,点击右上角预览即可。
- 前端配置解决 - 通过配置devServers proxy反向代理解决跨域。
- 错误配置:前端首先在manifest.json源码h5配置中添加反向代理配置,如下
"h5" : {
"router" : {
"base" : ""
},
"devServer" : {
"disableHostCheck" : true, //禁止访问本地host文件
"port" : 8000, //修改项目端口
"proxy" : {
/**配置服务器路径**/
"/api" : {
"target" : "https://dev.api.dajxyl.com",
"changeOrigin" : true,
/**重写路径**/
"pathRewrite": {
"^/api": ""
}
}
}
}
}
-
这样配置完成后重启项目,接口访问的路径就是target配置的路径了,但是当我重启项目访问接口时返回数据还是报了跨域的错误,按理说应该是没有问题的,但就是报错了,我想可能是哪里写错了或者没有加入关键性的参数,所以我又反复的查看了官方文档及社区有关跨域的讨论,百度了很多与此相关的文章,官方给出的代码,百度出来的解决代码和上面所写的代码基本没有差别,所以说上面的配置没有问题,问题出在别的地方。
-
解决 在反复查看配置外的代码逻辑没有问题后,还是没有找到问题所在,没办法只能重头一步一步打印接口请求过程(二次封装后的请求),发现在接口调用时传进来的url有些异常,我用promis二次封装了前端请求,有配置一个公用路径,调用接口时会默认使用这个配置路径,这样我在devServer proxy中配置的反向代理就被覆盖了,实际上还是以本地地址直接请求服务器地址,所以出现跨域。找到问题后就好解决了
-
正确解决方案 直接修改封装代码:
javascript
//api接口路径文档
let url = {
loginVerify:"/api/user/login", //用户登录接口
}
//使用async异步函数
//登录时检查当前账号是否已经注册过
export async function loginVerify(parmas){
return await dajxHttp.get({
url: url.loginVerify,
data:parmas,
})
}
主要改动在每个接口url前加上了devServers proxy配置中的 '前缀' 在请求封装体中不在使用全局基本路径而是使用反向代理的地址。
devServer proxy反向代理解决跨域的实现原理
- 跨域出现的原因-同源策略,跨域主要在浏览器端,接口请求数据大概分为三点:
-
浏览器向服务器发送请求。
-
服务器收到请求后将数据返回给浏览器。
-
浏览器对比服务器返回数据中header里的允许访问域名,判断该服务器是否允许当前域名访问(即判断服务器是否放开当前域名或所有域名),所以跨域问题一般在第三步上出现。
-
综上跨域是浏览器端的问题
-
devServer 原理其实就是http proxy,devServer是webpack中的配置,在h5项目中配置devServer proxy反向代理,相当于浏览器将请求发送给 devServer 再由 devServer 完整的将所有请求数据代发送给远端服务器。devServer 属于本地服务器不属于浏览器范畴所以不存在跨域,在接受到远端服务器返回的数据后再由devServer发送给浏览器,此时devServer和浏览器是本地数据交换不存在跨域,所以浏览器正常接收数据。如图: