参考资料
原文:
https://blog.csdn.net/enter89/article/details/51205752
https://blog.csdn.net/enter89/article/details/51205752
最近使用uni-app框架在做H5页面,在添加Token到请求头发送请求到后台请求数据的时候,前端页面控制台报错了。去查了很多资料,发现这是浏览器跨域请求产生的问题。
特此记录一下问题的原因和解决办法。
1、什么是跨域?
(1)由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一个与当前页面地址不同即为跨域。
跨域就指着协议,域名,端口不一致,出于安全考虑,跨域的资源之间是无法交互的(例如一般情况跨域的JavaScript无法交互,当然有很多解决跨域的方案)
(2)跨域问题的产生原因是浏览器的同源策略限制,不同域之间不能直接访问,需要经过一些处理才能访问。
2、跨域请求的种类有两种
(1) 简单跨域请求。
当HTTP请求出现以下两种情况时,浏览器认为是简单跨域请求:
1). 请求方法是GET、HEAD或者POST,并且当请求方法是POST时,Content-Type必须是application/x-www-form-urlencoded, multipart/form-data或着text/plain中的一个值。
2). 请求中没有自定义HTTP头部。
对于简单跨域请求,浏览器要做的就是在HTTP请求中添加Origin Header,将JavaScript脚本所在域填充进去,向其他域的服务器请求资源。服务器端收到一个简单跨域请求后,根据资源权限配置,在响应头中添加Access-Control-Allow-Origin Header。浏览器收到响应后,查看Access-Control-Allow-Origin Header,如果当前域已经得到授权,则将结果返回给JavaScript。否则浏览器忽略此次响应。
(2)带预检(Preflighted)的跨域请求。
当HTTP请求出现以下两种情况时,浏览器认为是带预检(Preflighted)的跨域请求:
1). 除GET、HEAD和POST(only with application/x-www-form-urlencoded, multipart/form-data, text/plain Content-Type)以外的其他HTTP方法。
2). 请求中出现自定义HTTP头部。类似下面的代码。
axios({
method:'get',
headers:{
Accept:'application/json',
Authorization:adasdfadfasdfsewe
},
params:{}
})
带预检(Preflighted)的跨域请求需要浏览器在发送真实HTTP请求之前先发送一个OPTIONS的预检请求,检测服务器端是否支持真实请求进行跨域资源访问,真实请求的信息在OPTIONS请求中通过Access-Control-Request-Method Header和Access-Control-Request-Headers Header描述,此外与简单跨域请求一样,浏览器也会添加Origin Header。
服务器端接到预检请求后,根据资源权限配置,在响应头中放入Access-Control-Allow-Origin Header、Access-Control-Allow-Methods和Access-Control-Allow-Headers Header,分别表示允许跨域资源请求的域、请求方法和请求头。此外,服务器端还可以加入Access-Control-Max-Age Header,允许浏览器在指定时间内,无需再发送预检请求进行协商,直接用本次协商结果即可。浏览器根据OPTIONS请求返回的结果来决定是否继续发送真实的请求进行跨域资源访问。这个过程对真实请求的调用者来说是透明的。
3、后台添加配置支持跨域请求
Access-Control-Allow-Origin是HTML5中定义的一种解决资源跨域的策略。
他是通过服务器端返回带有Access-Control-Allow-Origin标识的Response header,用来解决资源的跨域权限问题。
设置Access-Control-Allow-Origin来实现跨域访问比较简单。
httpServletResponse.setHeader("Access-Control-Allow-Origin","http://192.168.0.193:8081");
httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
httpServletResponse.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Depth, User-Agent, X-File-Size, X-Requested-With, X-Requested-By, If-Modified-Since, X-File-Name, X-File-Type, Cache-Control, Origin");
httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // 支持HTTP 1.1.
httpServletResponse.setHeader("Pragma", "no-cache"); // 支持HTTP 1.0. response.setHeader("Expires", "0");