java为什么会有跨域问题前言
相信大家在写前端脚本的时候经常会遇到发送数据到后台的情况,但是由于浏览器的限制 , 不同域名之间的数据是不能互相访问的,那前端怎么和后端如何进行数据之间的交换呢?
JavaScript由于安全性方面的考虑 , 不允许页面跨域调用其他页面的对象,那么问题来了 , 什么是跨域问题?
答:这是由于浏览器同源策略的限制,现在所有支持JavaScript的浏览器都使用了这个策略 。那么什么是同源呢?所谓的同源是指三个方面“相同”:
域名相同
协议相同
端口相同
下面就举几个例子来帮助更好的理解同源策略 。
URL
说明
是否允许通信
同一域名允许
不同域名不允许
同一域名不同端口不允许
同一域名不同协议不允许
在JAVA中处理跨域问题 , 通常有以下两种常用的解决方法 。
第一种解决方法
后台代码在被请求的Servlet中添加Header设置:
response.setHeader("Access-Control-Allow-Origin", "*");
PrintWriter out =null;
try
{
out = response.getWriter();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
out.print("{'status':'ok'}");
out.flush();
out.close();
Access-Control-Allow-Origin这个Header在W3C标准里用来检查该跨域请求是否可以被通过 , 如果值为*则表明当前页面可以跨域访问 。默认的情况下是不允许的 。
在前端JS中需要向Servlet发出请求,请求代码如下所示:
$.ajax({
url: "your url",
type:"get or post",
dataType:"json",
data:{
....
},
success:function(data){
...
}
第二种解决方法
通过jsonp跨域请求的方式 。JSONP和JSON虽然只有一个字母的区别,但是他们完全就是两回事,很多人很容易把他们搞混 。JSON是一种数据交换的格式,而JSONP则是一种非官方跨域数据交互协议 。
【java服务端跨域代码 java 跨域】首先来说一下前端JS是怎么发送请求 。代码如下所示:
$.ajax({
url:"your url",
type:"get or post",
async:false,
dataType : "jsonp",
//服务端用于接收callback调用的function名的参数
jsonp:"callbackparam",
//callback的function名称
jsonpCallback:"success_jsonpCallback",
success:function(data){
console.log(data);
},
error:function(data){
console.log(data);
}
});
这里的callbackparam和success_jsonpCallback可以理解为发送的data数据的键值对,可以自定义,但是callbackparam需要和后台约定好参数名称,因为后台需要获取到这个参数里面的值(即success_jsonpCallback) 。
下面,最重要的来了,后台怎么样获取和返回数据呢 。代码如下所示:
PrintWriter out =null;
String callback=req.getParameter("callbackparam");
String json=callback "({'status':'ok'})";
try
{
out = resp.getWriter();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
out.print(json);
out.flush();
out.close();
首先需要获取参数名为callbackparam的值,这里获取到的值就是“success_jsonpCallback” 。然后将这个值加上一对小括号 。小括号里放入你需要返回的数据内容,比如这里我返回一个JSON对象 。当然你也可以返回其他对象,比如只返回一个字符串类型数据也可以 。最后前端JS返回的数据就是这样的:
success_jsonpCallback({'status':'ok'})
浏览器会自动解析为json对象 , 这时候你只需要在success回调函数中直接用data.status就可以了 。
java服务器端怎么设置ajax 的跨域请求头在服务端设置response.setHeader("Access-Control-Allow-Origin", "*");即可 。
Access-Control-Allow-Origin:* 表示允许任何域名跨域访问
如果需要指定某域名才允许跨域访问,只需把Access-Control-Allow-Origin:*改为Access-Control-Allow-Origin:允许的域名
例如:response.setHeader("Access-Control-Allow-Origin", "");
我的一个java请求,该如何设置,别人就可以跨域访问我的请求得到数据一、通过jsonp跨域
在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的 。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的 。
比如,有个a.html页面,它里面的代码需要利用ajax获取一个不同域上的json数据,假设这个json数据地址是,那么a.html中的代码就可以这样:
我们看到获取数据的地址后面还有一个callback参数,按惯例是用这个参数名,但是你用其他的也一样 。当然如果获取数据的jsonp地址页面不是你自己能控制的,就得按照提供数据的那一方的规定格式来操作了 。
因为是当做一个js文件来引入的,所以返回的必须是一个能执行的js文件,所以这个页面的php代码可能是这样的:
最终那个页面输出的结果是:
所以通过得到的js文件,就是我们之前定义的dosomething函数,并且它的参数就是我们需要的json数据,这样我们就跨域获得了我们需要的数据 。
这样jsonp的原理就很清楚了,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数 , 并且会把我们需要的json数据作为参数传入 。所以jsonp是需要服务器端的页面进行相应的配合的 。
知道jsonp跨域的原理后我们就可以用js动态生成script标签来进行跨域操作了 , 而不用特意的手动的书写那些script标签 。如果你的页面使用jquery,那么通过它封装的方法就能很方便的来进行jsonp操作了 。
原理是一样的,只不过我们不需要手动的插入script标签以及定义回掉函数 。jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用 。$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数 。
2、通过修改document.domain来跨子域
浏览器都有一个同源策略,其限制之一就是第一种方法中我们说的不能通过ajax的方法去请求不同源中的文档 。它的第二个限制是浏览器中不同域的框架之间是不能进行js的交互操作的 。有一点需要说明,不同的框架之间(父子或同辈),是能够获取到彼此的window对象的,但蛋疼的是你却不能使用获取到的window对象的属性和方法(html5中的postMessage方法是一个例外 , 还有些浏览器比如ie6也可以使用top、parent等少数几个属性),总之,你可以当做是只能获取到一个几乎无用的window对象 。比如,有一个页面,它的地址是,在这个页面里面有一个iframe,它的src是, 很显然,这个页面与它里面的iframe框架是不同域的 , 所以我们是无法通过在页面中书写js代码来获取iframe中的东西的:
这个时候,document.domain就可以派上用场了 , 我们只要把 和 这两个页面的document.domain都设成相同的域名就可以了 。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域 , 且主域必须相同 。例如:a.b.example.com 中某个文档的document.domain 可以设成a.b.example.com、b.example.com 、example.com中的任意一个,但是不可以设成 c.a.b.example.com,因为这是当前域的子域 , 也不可以设成baidu.com,因为主域已经不相同了 。
在页面中设置document.domain:
在页面中也设置document.domain,而且这也是必须的,虽然这个文档的domain就是example.com,但是还是必须显示的设置document.domain的值:
这样我们就可以通过js访问到iframe中的各种属性和对象了 。
不过如果你想在 页面中通过ajax直接请求 页面,即使你设置了相同的document.domain也还是不行的,所以修改document.domain的方法只适用于不同子域的框架间的交互 。如果你想通过ajax的方法去与不同子域的页面交互,除了使用jsonp的方法外,还可以用一个隐藏的iframe来做一个代理 。原理就是让这个iframe载入一个与你想要通过ajax获取数据的目标页面处在相同的域的页面,所以这个iframe中的页面是可以正常使用ajax去获取你要的数据的,然后就是通过我们刚刚讲得修改document.domain的方法,让我们能通过js完全控制这个iframe,这样我们就可以让iframe去发送ajax请求,然后收到的数据我们也可以获得了 。
3、使用window.name来进行跨域
window对象有个name属性 , 该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置 。
比如:有一个页面a.html,它里面有这样的代码:
再看看b.html页面的代码:
a.html页面载入后3秒,跳转到了b.html页面,结果为:
我们看到在b.html页面上成功获取到了它的上一个页面a.html给window.name设置的值 。如果在之后所有载入的页面都没对window.name进行修改的话,那么所有这些页面获取到的window.name的值都是a.html页面设置的那个值 。当然 , 如果有需要 , 其中的任何一个页面都可以对window.name的值进行修改 。注意 , window.name的值只能是字符串的形式,这个字符串的大小最大能允许2M左右甚至更大的一个容量,具体取决于不同的浏览器,但一般是够用了 。
上面的例子中,我们用到的页面a.html和b.html是处于同一个域的,但是即使a.html与b.html处于不同的域中,上述结论同样是适用的,这也正是利用window.name进行跨域的原理 。
下面就来看一看具体是怎么样通过window.name来跨域获取数据的 。还是举例说明 。
比如有一个页面,需要通过a.html页面里的js来获取另一个位于不同域上的页面里的数据 。
data.html页面里的代码很简单,就是给当前的window.name设置一个a.html页面想要得到的数据值 。data.html里的代码:
那么在a.html页面中 , 我们怎么把data.html页面载入进来呢?显然我们不能直接在a.html页面中通过改变window.location来载入data.html页面 , 因为我们想要即使a.html页面不跳转也能得到data.html里的数据 。答案就是在a.html页面中使用一个隐藏的iframe来充当一个中间人角色,由iframe去获取data.html的数据,然后a.html再去得到iframe获取到的数据 。
充当中间人的iframe想要获取到data.html的通过window.name设置的数据,只需要把这个iframe的src设为就行了 。然后a.html想要得到iframe所获取到的数据 , 也就是想要得到iframe的window.name的值,还必须把这个iframe的src设成跟a.html页面同一个域才行 , 不然根据前面讲的同源策略,a.html是不能访问到iframe里的window.name属性的 。这就是整个跨域过程 。
看下a.html页面的代码:
上面的代码只是最简单的原理演示代码,你可以对使用js封装上面的过程,比如动态的创建iframe,动态的注册各种事件等等,当然为了安全,获取完数据后,还可以销毁作为代理的iframe 。网上也有很多类似的现成代码,有兴趣的可以去找一下 。
通过window.name来进行跨域,就是这样子的 。
4、使用HTML5中新引进的window.postMessage方法来跨域传送数据
window.postMessage(message,targetOrigin)方法是html5新引进的特性 , 可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8 、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法 。
调用postMessage方法的window对象是指要接收消息的那一个window对象 , 该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 *。
需要接收消息的window对象,可是通过监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中 。
上面所说的向其他window对象发送消息,其实就是指一个页面有几个框架的那种情况,因为每一个框架都有一个window对象 。在讨论第二种方法的时候,我们说过,不同域的框架间是可以获取到对方的window对象的 , 而且也可以使用window.postMessage这个方法 。下面看一个简单的示例,有两个页面
我们运行a页面后得到的结果:
我们看到b页面成功的收到了消息 。
使用postMessage来跨域传送数据还是比较直观和方便的,但是缺点是IE6、IE7不支持,所以用不用还得根据实际需要来决定 。
结语:
除了以上几种方法外,还有flash、在服务器上设置代理页面等跨域方式 , 这里就不做介绍了 。
以上四种方法,可以根据项目的实际情况来进行选择应用 , 个人认为window.name的方法既不复杂,也能兼容到几乎所有浏览器,这真是极好的一种跨域方法 。
根据具体问题类型,进行步骤拆解/原因原理分析/内容拓展等 。
具体步骤如下:/导致这种情况的原因主要是……
关于java服务端跨域代码和java 跨域的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站 。
推荐阅读
- 硬盘隐藏了怎么恢复,硬盘里的隐藏文件怎么找出来
- chatgpt改英文版简历,chatGpt简历筛选
- chatgpt会爬网站数据吗,爬网站数据算犯法吗
- go语言grpc服务开启 grpc支持的语言
- 服务器安全加固,服务器安全加固软件厂家
- 独立显卡手机参数怎么看,独立显卡怎么看性能参数
- vb.net控件变量 vb控件属性设置
- 桥梁拍摄配乐叫什么,桥梁拍摄技巧
- css3边框属性实例讲解,css边框代码大全