跨域解决方案
1、 跨域资源共享 CORS
简单请求:
前端: var xhr = new XMLHttpRequest(); xhr.withCredentials = true; vue中: // 全局加法 Vue.http.interceptors.push(function(request, next) {//拦截器 // 跨域携带cookie request.credentials = true; next() }) // 个别请求 this.$http.get('xxxx',{params: 参数对象,credentials: true}) 后端: if(request.getHeader("Origin").contains("mydomain.com")) { response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); } 需要注意的是,如果要发送Cookie,Access-Control-Allow-Origin就不能设为星号,
必须指定明确的、与请求网页一致的域名。同时,Cookie依然遵循同源政策,
只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie也无法读取服务器域名下的Cookie。
2、非简单请求
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT
或DELETE
,或者Content-Type
字段的类型是application/json
。
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。
// 服务器返回字段 Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: X-Custom-Header Access-Control-Allow-Credentials: true Access-Control-Max-Age: 1728000 (1)Access-Control-Allow-Methods 该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。 (2)Access-Control-Allow-Headers 如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。 (3)Access-Control-Allow-Credentials 该字段与简单请求时的含义相同。 (4)Access-Control-Max-Age 该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。 4.3 浏览器的正常请求和回应 一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。 下面是"预检"请求之后,浏览器的正常CORS请求。 PUT /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com X-Custom-Header: value Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0... 上面头信息的Origin字段是浏览器自动添加的。 下面是服务器正常的回应。 Access-Control-Allow-Origin: http://api.bob.com Content-Type: text/html; charset=utf-8
3、jsonp跨域
jsonp跨域其实也是JavaScript设计模式中的一种代理模式。在html页面中通过相应的标签从不同域名下加载静态资源文件是被浏览器允许的,
所以我们可以通过这个“犯罪漏洞”来进行跨域。一般,我们可以动态的创建script标签,再去请求一个带参网址来实现跨域通信
//原生的实现方式 let script = document.createElement('script'); script.src = 'http://www.nealyang.cn/login?username=Nealyang&callback=callback'; document.body.appendChild(script); function callback(res) { console.log(res); }
当然,jquery也支持jsonp的实现方式
$.ajax({ url:'http://www.nealyang.cn/login', type:'GET', dataType:'jsonp',//请求方式为jsonp jsonpCallback:'callback', data:{ "username":"Nealyang" } })
java:
JSONObject resultJSON = JSONObject.fromObject(map); //根据需要拼装json String jsonpCallback = request.getParameter("jsonpCallback");//客户端请求参数 out.println(jsonpCallback+"("+resultJSON.toString(1,1)+")");//返回jsonp格式数据
虽然这种方式非常好用,但是一个最大的缺陷是,只能够实现get请求
CORS与JSONP的使用目的相同,但是比JSONP更强大。
JSONP只支持GET
请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。