什么是跨域?
跨域是浏览器的同源策略禁止访问另一个域的资源,
同源
同源策略:same origin policy,如果两个资源(页面)协议,域名,端口都相同,那么就是同源。 即使:两个不同域名指向同一个ip,也算非同源
前端解决跨域的方法
- jsonp 原理:浏览器在加载script标签的时候可以加载另一个域下的资源,而js标签类似get请求,且返回数据是json格式 使用:
var script = document.createElement('script')
script.style = 'text/javascript'
//将要请求的get地址传到script的src属性,并且添加回调函数 script.setAttribute('scr','http://www.domain2.com:8080/login?user=admin&callback=handleCallback')
//将script标签放入文档
document.head.appendChild(script)
//执行回调函数
function handleCallback(res){
//处理JSON格式数据
alert(JSON.stringify(res)) }
由于请求script只能是get方法,所以JSONP这种方式只能解决get请求,post或者其他http方法无法解决
-
跨域资源共享 原理:
-
- cross-origin -resouce sharing跨域资源共享,允许浏览器向跨源服务器发出http请求,需要浏览器和服务器同时支持
-
- 浏览器在发出跨域请求时:1。简单请求,直接在头部信息中带上origin信息,标识属于哪个源,服务端配置
access-control-allow-origin接受哪些域名跨域访问,可以是*允许所有 - 如果是非简单请求会在正式请求之前,发送预检请求
- 浏览器在发出跨域请求时:1。简单请求,直接在头部信息中带上origin信息,标识属于哪个源,服务端配置
-
简单来说(简单请求):
-
是一个双端配合,允许打卡跨域资源限制的一种手段
-
浏览器端:请求头携带origin信息
-
服务端:配置
access-control-allow-origin允许哪些源跨域 -
代码:
-
- 原生:
xmlHttpRequest不需要配置请求头,简单请求会自动带上origin属性
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容 xhr.open('post', 'http://www.domain2.com:8080/login', true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send('user=admin'); xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { alert(xhr.responseText); } }; - 原生:
-
- AJAX:有一个属性
crossDomain,配置为true之后会让请求头携带orgin跨域额外信息,但是不会自动包含cookie
$.ajax({ ... xhrFields: { withCredentials: true // 前端设置是否带cookie }, crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie ... }); - AJAX:有一个属性
-
VUE中的axios,默认也会把origin放到请求头,不需要额外配置
-
-
服务端配置
/* * 导入包: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"); -
反向代理(NodeJs中间件代理跨域)(Vue代理跨域)(nginx转发代理)
-
场景:当服务器端无法修改cors,并且client全部换成jsonp方式比较繁琐时,只能通过中间代理服务器,将代理服务器设置为支持CORS或者代理服务器和请求页面同源,使页面可以直接请求代理服务器,在通过代理服务器进行接口代理,代理请求目标接口地址,返回数据
-
原理:跨域限制仅是浏览器端的安全策略,并不是http协议的固有限制,所以中间服务器在参数和cookie有效的情况下是可以正常的请求目标服务器的,Vue(
node+webpack+webpack-dev-server)中配置proxy就是启动一个同源的服务进行接口代理 -
注意:
- 1.非vue ,webpack,dev-serve服务,单独启的nginx或者node express服务做反向代理时,一般是跟页面非同源,非同源要访问代理服务器也存在跨域问题,需要配置
cors允许跨域访问,配置access-control-allow-header - 在webpack-dev-server服务,默认应该是基本与测试环境页面同源,不需要配置请求头允许 代码:
- 1.非vue ,webpack,dev-serve服务,单独启的nginx或者node express服务做反向代理时,一般是跟页面非同源,非同源要访问代理服务器也存在跨域问题,需要配置
-
webpack-dev-server代理
module.exports = {
entry: {},
module: {},
...
devServer: {
historyApiFallback: true,
proxy: [{
context: '/login',
target: 'http://www.domain2.com:8080', // 代理跨域目标接口
changeOrigin: true,
secure: false, // 当代理某些https服务报错时用
cookieDomainRewrite: 'www.domain1.com' // 可以为false,表示不修改
}],
noInfo: true
}
}