java代码跨域问题 java解决跨域的几种办法

Spring MVC 的跨域解决方案

一句话:同一个ip、同一个网络协议、同一个端口,三者都满足就是同一个域,否则就是跨域。

创新互联建站是一家专注于成都做网站、网站设计与策划设计,达拉特网站建设哪家好?创新互联建站做网站,专注于网站建设10多年,网设计领域的专业建站公司;建站业务涵盖:达拉特等地区。达拉特做网站价格咨询:18980820575

基于两个方面:

a. web应用本身是部署在不同的服务器上

b.基于开发的角度 --- 前后端分离

web应用本身是部署在不同的服务器上,对应的域名也就有所不同

比如百度。

主域名:

二级域名:, ,

需要在不同的域之间,通过ajax方式互相请求,是非常常见的需求。

Spring 4中增加了对jsonp的原生支持,只需要ControllerAdvice就可以开启,方法如下:

首先新建一个Advice类,我们叫做“JsonpAdvice”,然后在里面定义接收jsonp请求的参数key:

@ControllerAdvice("cn.isy.web.sso.web")指定作用的包名

supper("callback")指定的是url中callback:

注意:

我们还可以重写AbstractJsonpResponseBodyAdvice中的feforeBodyWriteInternal方法:

做到实现url携带callback就返回jsonp格式,没有就返回正常格式

img

controller中

controller中的代码正常编写就OK,不用修改任何东西。

只要保证在cn.isy.web.sso.web包下即可!

jquery ajax

注意:必须使用jsonp的方式提交请求!

有关cors的介绍可以去详细看一下,这里就不作重复了:

CORS详解

跨资源共享CORS详解

主要配置

使用注解CrossOrigin

在controller类上添加CrossOrigin注解表示当前类中的所有入口函数都

可以实现跨域。也可以指定某个conroller中具体的方法。

img

了解一下这个注解的内容:

img

jquery ajax的写法

注意:这里不用使用jsonp的方式请求普通的ajax即可!,因为浏览器自己可以去做!

CORS全局配置

自己试了试没有成功!

资料

解释cors的原理不错

让自己变得更优秀才可以有更多资源

搜索微信号(ID:芋道源码),可以获得各种 Java 源码解析。

并且,回复【书籍】后,可以领取笔者推荐的各种 Java 从入门到架构的书籍。

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则是一种非官方跨域数据交互协议。

首先来说一下前端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请求,该如何设置别人就可以跨域访问我的请求得到数据?

一、通过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的方法既不复杂,也能兼容到几乎所有浏览器,这真是极好的一种跨域方法。

根据具体问题类型,进行步骤拆解/原因原理分析/内容拓展等。

具体步骤如下:/导致这种情况的原因主要是……

如何解决跨域问题

由 于此前很少写前端的代码(哈哈,不合格的程序员啊),最近项目中用到json作为系统间交互的手段,自然就伴随着众多ajax请求,随之而来的就是要解决 ajax的跨域问题。本篇将讲述一个小白从遇到跨域不知道是跨域问题,到知道是跨域问题不知道如何解决,再到解决跨域问题,最后找到两种方法解决ajax 跨域问题的全过程。

不知是跨域问题

起 因是这样的,为了复用,减少重复开发,单独开发了一个用户权限管理系统,共其他系统获取认证与授权信息,暂且称之为A系统;调用A系统以B为例。在B系统 中用ajax调用A系统系统的接口(数据格式为json),当时特别困惑,在A系统中访问相应的url可正常回返json数据,但是在B系统中使用 ajax请求同样的url则一点儿反应都没有,好像什么都没有发生一样。这样反反复复改来改去好久都没能解决,于是求救同事,提醒可能是ajax跨域问 题,于是就将这个问题当做跨域问题来解决了。

知跨域而不知如何解决

知道问题的确切原因,剩下的就是找到解决问题的方法了。google了好久,再次在同事的指点下知道jQuery的ajax有jsonp这样的属性可以用来解决跨域的问题。

找到一种解决方式

现在也知道了怎样来解决跨域问题,余下的就是实现的细节了。实现的过程中错误还是避免不了的。由于不了解json和jsonp两种格式的区别,也犯了错误,google了好久才解决。

首先来看看在页面中如何使用jQuery的ajax解决跨域问题的简单版:

复制代码

$(document).ready(function(){

var url='"

+"?id=1callback=?';

$.ajax({

url:url,

dataType:'jsonp',

processData: false,

type:'get',

success:function(data){

alert(data.name);

},

error:function(XMLHttpRequest, textStatus, errorThrown) {

alert(XMLHttpRequest.status);

alert(XMLHttpRequest.readyState);

alert(textStatus);

}});

});

复制代码

这样写是完全没有问题的,起先error的处理函数中仅仅是alert(“error”),为了进一步弄清楚是什么原因造成了错误,故将处理函数变 为上面的实现方式。最后一行alert使用为;parsererror。百思不得其解,继续google,最终还是在万能的stackoverflow找 到了答案,链接在这里。原因是jsonp的格式与json格式有着细微的差别,所以在server端的代码上稍稍有所不同。

比较一下json与jsonp格式的区别:

json格式:

{

"message":"获取成功",

"state":"1",

"result":{"name":"工作组1","id":1,"description":"11"}

}

jsonp格式:

callback({

"message":"获取成功",

"state":"1",

"result":{"name":"工作组1","id":1,"description":"11"}

})

看出来区别了吧,在url中callback传到后台的参数是神马callback就是神马,jsonp比json外面有多了一层,callback()。这样就知道怎么处理它了。于是修改后台代码。

后台java代码最终如下:

复制代码

@RequestMapping(value = "/getGroupById")

public String getGroupById(@RequestParam("id") Long id,

HttpServletRequest request, HttpServletResponse response)

throws IOException {

String callback = request.getParameter("callback");

ReturnObject result = null;

Group group = null;

try {

group = groupService.getGroupById(id);

result = new ReturnObject(group, "获取成功", Constants.RESULT_SUCCESS);

} catch (BusinessException e) {

e.printStackTrace();

result = new ReturnObject(group, "获取失败", Constants.RESULT_FAILED);

}

String json = JsonConverter.bean2Json(result);

response.setContentType("text/html");

response.setCharacterEncoding("utf-8");

PrintWriter out = response.getWriter();

out.print(callback + "(" + json + ")");

return null;

}

复制代码

注意这里需要先将查询结果转换我json格式,然后用参数callback在json外面再套一层,就变成了jsonp。指定数据类型为jsonp的ajax就可以做进一步处理了。

虽然这样解决了跨域问题,还是回顾下造成parsererror的原因。原因在于盲目的把json格式的数据当做jsonp格式的数据让ajax处理,造成了这个错误,此时server端代码是这样的:

复制代码

@RequestMapping(value = "/getGroupById")

@ResponseBody

public ReturnObject getGroupById(@RequestParam("id") Long id,

HttpServletRequest request, HttpServletResponse response){

String callback = request.getParameter("callback");

ReturnObject result = null;

Group group = null;

try {

group = groupService.getGroupById(id);

result = new ReturnObject(group, "获取成功", Constants.RESULT_SUCCESS);

} catch (BusinessException e) {

e.printStackTrace();

result = new ReturnObject(group, "获取失败", Constants.RESULT_FAILED);

}

return result;

}

复制代码

至此解决ajax跨域问题的第一种方式就告一段落。

追加一种解决方式

追求永无止境,在google的过程中,无意中发现了一个专门用来解决跨域问题的jQuery插件-jquery-jsonp。

有第一种方式的基础,使用jsonp插件也就比较简单了,server端代码无需任何改动。

来看一下如何使用jquery-jsonp插件解决跨域问题吧。

复制代码

var url=""

+"?id=1callback=?";

$.jsonp({

"url": url,

"success": function(data) {

$("#current-group").text("当前工作组:"+data.result.name);

},

"error": function(d,msg) {

alert("Could not find user "+msg);

}

});


网页名称:java代码跨域问题 java解决跨域的几种办法
本文地址:http://hbruida.cn/article/dojedeg.html