什么是跨域
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。
跨域指的是浏览器不能执行其它网站的脚本。是由浏览器的同源策略造成的,是浏览器对JavaScript 施加的安全限制。
有一点必须要注意:跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。之所以会跨域,是因为受到了同源策略的限制,同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致。
什么是同源策略?
协议号 - 域名 - 端口号
,只有当这三个条件同时满足相同时,我们就称之为符合同源策略,同源策略也可以看做是一个协议。
https:// www.baidu.com :8080 /test 协议号 域名 端口号 路径
通常我们导航的url都是由这四部分组成的。
同源策略限制行为:
Cookie
、LocalStorage
和IndexDB
无法读取;
- 无法获得非同源网页的 DOM节点;
AJAX
请求不能发送;
<img src=XXX> <link href=XXX> <script src=XXX>
跨域解决方法
1.Proxy代理
webpack本地代理
【前端解决:只适用于本地开发环境,上线了解决不了,直接把dist放在后端服务器中】
Proxy通过服务端接口转发来实现对于跨域问题的问题,因为HTTP同源策略只在浏览器中生效。 这里介绍几种不同Proxy代理方法:
在vue.config.js中利用 WebpackDevServer 配置本地代理
// 配置实例: module.exports = { //... devServer: { proxy: { '/api': { target: 'xxx', pathRewrite: { '^/api': '' }, changeOrigin: true } } } };
注意:项目上线需要把打包后的文件放在服务器上运行,而不是启动脚手架运行,也就没有内置web服务器做代理,所以此方式只适用于开发测试阶段
上线时需要使用nginx代理或者服务器配置cors(每种语言有自己不同的配置方式)
参考:Vue中如何解决跨域问题
Nginx反向代理
server { #nginx监听所有localhost:8080端口收到的请求 listen 8080; server_name localhost; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; #localhost:8080 会被转发到这里 #同时, 后端程序会接收到 "192.168.25.20:8088"这样的请求url location / { proxy_pass http://192.168.25.20:8088; } #localhost:8080/api/ 会被转发到这里 #同时, 后端程序会接收到 "192.168.25.20:9000/api/"这样的请求url location /api/ { proxy_pass http://192.168.25.20:9000; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }
2.跨域资源共享 CORS
目前最主流、最简单的方案,直接让后端设置响应头,允许资源共享就ok了
CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。
1、普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
2、带cookie跨域请求:前后端都需要进行设置
【前端设置】根据xhr.withCredentials字段判断是否带有cookie
vue框架
- vue-resource
Vue.http.options.credentials = true
- axios
axios.defaults.withCredentials = true
【服务端设置】
服务器端对于CORS的支持,主要是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。若后端设置成功,前端浏览器控制台则不会出现跨域报错信息,反之,说明没设成功。
Java后台
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * 导入包:import javax.servlet.http.HttpServletResponse; * 接口参数中定义:HttpServletResponse response */ // 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/' response.setHeader( "Access-Control-Allow-Origin" , "http://www.domain1.com" ); // 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示 response.setHeader( "Access-Control-Allow-Credentials" , "true" ); // 提示OPTIONS预检时,后端需要设置的两个常用自定义头 response.setHeader( "Access-Control-Allow-Headers" , "Content-Type,X-Requested-With" ); |
3.JSONP
JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。
核心思想:网页通过添加一个元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
this.$http.jsonp('http://www.domain2.com:8080/login', { params: {}, jsonp: 'handleCallback' }).then((res) => { console.log(res); })