有个朋友在写扇贝插件的时候遇到了跨域问题。
因而我对解决跨域问题的方式进行了一番探讨。javascript
问题css
API:查询单词
URL: https://api.shanbay.com/bdc/search/?word={word}
请求方式: GET
参数: {word}, 必须,要查询的单词html
报错为前端
XMLHttpRequest cannot load http://localhost/home/saveCandidate. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 404.
这就是典型的跨域问题。java
可是我在浏览器里输入URL是能够进行查询单词的操做的,有什么不一样,即下面两个问题node
通过Google和本身测试jquery
同源策略:web
同源指的是域名(或IP),协议,端口都相同,不一样源的客户端脚本(javascript、ActionScript)在没明确受权的状况下,不能读写对方的资源。ajax
URL | 解释 | 是否跨域 |
---|---|---|
http://www.morethink.cn | 原来的URL | |
http://www.image.morethink.cn | 子域名 | 跨域(cookie也没法访问) |
http://morethink.cn | 不加www | 跨域 |
https://www.morethink.cn | 更改协议 | 跨域 |
http://www.morethink.cn:8080 | 更改端口号 | 跨域 |
缘由:json
同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
设想这样一种状况:A网站是一家银行,用户登陆之后,又去浏览其余网站。若是其余网站能够读取A网站的Cookie,会发生什么?
很显然,若是Cookie包含隐私(好比存款总额),这些信息就会泄漏。更可怕的是,Cookie每每用来保存用户的登陆状态,若是用户没有退出登陆,其余网站就能够冒充用户,随心所欲。由于浏览器同时还规定,提交表单不受同源政策的限制。
因而可知,"同源政策"是必需的,不然 Cookie 能够共享,互联网就毫无安全可言了。
同源策略限制如下几种行为:
测试URL为 http://localhost:80/home/allProductions
能够直接在浏览器console
中执行
var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://localhost:80/home/allProductions',true); xhr.send(); xhr.onreadystatechange=function() { if(xhr.readyState == 4) { if(xhr.status == 200) { console.log(JSON.parse(xhr.responseText)); } } }
在任意网站打开控制台,执行此段代码能够模拟跨域请求。
在知乎控制台打开报错以下
Mixed Content: The page at 'https://www.zhihu.com/question/26376773' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://localhost/home/allProductions'. This request has been blocked; the content must be served over HTTPS.
由于知乎是https,报错与普通的http协议不一样。
再澄清一下跨域问题:
在博客园控制台打开报错以下
XMLHttpRequest cannot load http://localhost/home/allProductions. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.cnblogs.com' is therefore not allowed access.
解决方案有不少
这里主要介绍SpringMVC解决跨域问题的方式。
能够直接参考Spring MVC 4.1 支持jsonp进行配置你的SpringMVC注解
我虽然请求不了json数据,可是我能够请求一个Content-Type
为application/javascript
的JavaScript对象,这样就能够避免浏览器的同源策略。
就是当服务器接受到名为jsonp
或者callback
的参数时,返回Content-Type: application/javascript
的结果,从而避免浏览器的同源策略检测。
在控制台中直接进行测试你的jsonp是否配置成功:
function println(data) { console.log(data); } var url = "http://localhost:80/home/allProductions?&callback=println"; // 建立script标签,设置其属性 var script = document.createElement('script'); script.setAttribute('src', url); // 把script标签加入head,此时调用开始 document.getElementsByTagName('head')[0].appendChild(script);
使用JQuery测试你的jsonp是否配置成功,由于控制台不能直接加载JQuery,须要本身创建html文件来进行测试:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="http://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></script> <script type="text/javascript"> function println(data) { console.log(data); console.log('print'); } function jsonp_test() { $.ajax({ type: "get", url: "http://localhost:80/home/allProductions", dataType: "jsonp", jsonp: "callback",//传递给请求处理程序或页面的,用以得到jsonp回调函数名的参数名(通常默认为:callback) jsonpCallback: "println", //返回后调用的处理函数 error: function () { //请求出错的处理 alert("请求出错"); } }); } </script> </head> <body onload="jsonp_test()"> </body> </html>
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它容许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
CORS须要浏览器和服务器同时支持。
即CORS与普通请求代码同样。
CORS与JSONP相比
@CrossOrigin
注解此注解既可用于方法也可用于类
源码以下:
@CrossOrigin(origins = "http://www.zhihu.com") @RequestMapping(value = "/allProductions", method = RequestMethod.GET) public Result getAllOldProductions() { }
@CrossOrigin
注解既可注解在方法上,也可注解在类上。
完成配置以后
全部跨域请求均可以访问
<mvc:cors> <mvc:mapping path="/**" /> </mvc:cors>
更加细粒度的配置:
<mvc:cors> <mvc:mapping path="/api/**" allowed-origins="http://domain1.com, http://domain2.com" allowed-methods="GET, PUT" allowed-headers="header1, header2, header3" exposed-headers="header1, header2" allow-credentials="false" max-age="123" /> <mvc:mapping path="/resources/**" allowed-origins="http://domain1.com" /> </mvc:cors>
WebSocket是一种通讯协议,使用ws://(非加密)和wss://(加密)做为协议前缀,在2008年诞生,2011年成为国际标准。全部浏览器都已经支持了。
它的最大特色就是,服务器能够主动向客户端推送信息,客户端也能够主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
该协议不实行同源政策,只要服务器支持,就能够经过它进行跨源通讯。
请求头信息:(多了个 origin)
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://example.com
响应头:(若是origin在白名单内)
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat
HTTP/2只是对HTML、CSS等JS资源的传输方式进行了优化,并无提供新的JS API,不能用于实时传输消息,也没法推送指定的信息。
参考文档: