javaWeb - 同源策略: Jsonp & CORS
博文内容总结自文章:浏览器家族的安全反击战
同源策略
同源是指{protocol,host,port} 这三个东西必须得一样! 例如有这么一个网页: http://www.store.com/product/page.html, 下面的表格列出了各种不同情况:
使用同源策略的原因
- Cookie失窃,非法网页通过javascript访问其他应用的服务器,获取到Cookie后伪装成用户进行非法操作。
- 通过iframe伪装form,将信息提交到恶意action,隐私数据提交到了不法网站,信息被盗取。
同源策略的限制
有src属性的标签不受同源策略的影响。比如script、img、iframe、link。相当于浏览器发送get请求。原页面的js不能访问通过src加载的资源。
如果两个网页的一级域名是相同的,他们可以共享cookie, 不过cookie的domain一定要设置为那个一级域名才可以,例如:
”document.cookie = ‘test=true;path=/;domain=store.com’”
对于浏览器来说:除了DOM、Cookie、LocalStorage、XMLHttprequest(Ajax)会受到同源策略的限制外,浏览器加载的第三方插件也有各自的同源策略。例如:flash,java applet,silverlight等。
既然服务器(domain)之间是互信的,那一个服务器(domain)可以设置一个白名单,里边列出它允许哪些服务器(domain)的AJAX请求。假设movie.com的白名单中有book.com, 那当属于book.com的JavaScript试图访问movie.com的时候,book.com先询问movie的白名单中是否有自己(是否允许自己访问),有就继续访问。
这个方法叫做Cross Origin Resource Sharing,简称CORS,只不过这个方法需要服务器的配合。
jsonp
jsonp 的原理很简单,利用了【前端请求静态资源的时候不存在跨域问题】这个思路,但是只支持 get。既然这个方法叫 jsonp,后端数据一定要使用 json 数据。
前端 jQuery 写法
$.ajax({
url:"http://crossdomain.com/services.php",
dataType:'jsonp',
data:'',
jsonp:'callback',
success:function(result) {
for(var i in result) {
alert(i+":"+result[i]);//循环输出a:1,b:2,etc.
}
},
timeout:3000
});
后端 SpringMVC 配置
@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpAdvice(){
// 这样如果请求中带 callback 参数,Spring 就知道这个是 jsonp 的请求了
super("callback");
}
}
以上写法要求 SpringMVC 版本不低于 3.2 。
原理
首先在客户端注册一个callback方法(javaScript定义一个指定名字的回调方法), 然后把callback的名字传给服务器。服务器先生成 json 数据。然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的回调函数的名字。
最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数)
CORS
Cross-Origin Resource Sharing
通过服务器端中转,例如你是来自book.com的, 现在想访问movie.com,那可以让那个book.com把请求转发给movie.com!利用了代理模式,book.com就是代理人。但在正式访问之前需要先发送预检请求(preflight request)确认自己能访问。
跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。参考文章:HTTP访问控制(CORS)
CORS需要服务器的配合,CORS 支持以下浏览器,不过目前来看,浏览器的问题已经越来越不重要了。
Chrome 3+
Firefox 3.5+
Opera 12+
Safari 4+
Internet Explorer 8+
前端 jQuery 写法
$.ajax({
type: "POST",
url: "...url...",
dataType: 'json',
crossDomain: true,
xhrFields: {
withCredentials: true
},
data: {
name: "name_from_frontend"
},
success: function (response) {
console.log(response)// 返回的 json 数据
$("#response").val(JSON.stringify(response));
}
});
crossDomain: true,这里代表使用跨域请求
xhrFields: {withCredentials: true},这样配置就可以把 cookie 带过去了,不然 session 无法维护(cookie中保存了JSESSIONID),如果没有这个需求,也就不需要配置。
推荐阅读
-
jsonp实现浏览器跨域请求 解决同源策略问题
-
javaWeb - 同源策略: Jsonp & CORS
-
解决同源策略限制以实现跨域访问的两个方法:JSONP和CORS
-
同源策略与JSONP劫持原理
-
深入浅析同源与跨域,jsonp(函数封装),CORS原理
-
ajax请求总是不成功?浏览器的同源策略和跨域问题详解 jsonp
-
同源策略与JSONP劫持原理
-
Firebug报错:已阻止交叉源请求:同源策略不允许读取XXX上的远程资源。可以将资源移动到相同的域名上或者启用 CORS 来解决这个问题
-
Firebug报错:已阻止交叉源请求:同源策略不允许读取XXX上的远程资源。可以将资源移动到相同的域名上或者启用 CORS 来解决这个问题
-
深入浅析同源与跨域,jsonp(函数封装),CORS原理