我的一个java请求,该如何设置,别人就可以跨域访问我的请求得到数据

我的一个java请求,该如何设置,别人就可以跨域访问我的请求得到数据,第1张

一、通过jsonp跨域

在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。

比如,有个ahtml页面,它里面的代码需要利用ajax获取一个不同域上的json数据,假设这个json数据地址是http://examplecom/dataphp,那么ahtml中的代码就可以这样:

我们看到获取数据的地址后面还有一个callback参数,按惯例是用这个参数名,但是你用其他的也一样。当然如果获取数据的jsonp地址页面不是你自己能控制的,就得按照提供数据的那一方的规定格式来操作了。

因为是当做一个js文件来引入的,所以http://examplecom/dataphp返回的必须是一个能执行的js文件,所以这个页面的php代码可能是这样的:

最终那个页面输出的结果是:

所以通过http://examplecom/dataphpcallback=dosomething得到的js文件,就是我们之前定义的dosomething函数,并且它的参数就是我们需要的json数据,这样我们就跨域获得了我们需要的数据。

这样jsonp的原理就很清楚了,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。

知道jsonp跨域的原理后我们就可以用js动态生成script标签来进行跨域操作了,而不用特意的手动的书写那些script标签。如果你的页面使用jquery,那么通过它封装的方法就能很方便的来进行jsonp操作了。

原理是一样的,只不过我们不需要手动的插入script标签以及定义回掉函数。jquery会自动生成一个全局函数来替换callback=中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用。$getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。

2、通过修改documentdomain来跨子域

浏览器都有一个同源策略,其限制之一就是第一种方法中我们说的不能通过ajax的方法去请求不同源中的文档。 它的第二个限制是浏览器中不同域的框架之间是不能进行js的交互操作的。有一点需要说明,不同的框架之间(父子或同辈),是能够获取到彼此的window对象的,但蛋疼的是你却不能使用获取到的window对象的属性和方法(html5中的postMessage方法是一个例外,还有些浏览器比如ie6也可以使用top、parent等少数几个属性),总之,你可以当做是只能获取到一个几乎无用的window对象。比如,有一个页面,它的地址是http://wwwexamplecom/ahtml  , 在这个页面里面有一个iframe,它的src是http://examplecom/bhtml, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的:

这个时候,documentdomain就可以派上用场了,我们只要把http://wwwexamplecom/ahtml 和 http://examplecom/bhtml这两个页面的documentdomain都设成相同的域名就可以了。但要注意的是,documentdomain的设置是有限制的,我们只能把documentdomain设置成自身或更高一级的父域,且主域必须相同。例如:abexamplecom 中某个文档的documentdomain 可以设成abexamplecom、bexamplecom 、examplecom中的任意一个,但是不可以设成 cabexamplecom,因为这是当前域的子域,也不可以设成baiducom,因为主域已经不相同了。

在页面 http://wwwexamplecom/ahtml 中设置documentdomain:

在页面 http://examplecom/bhtml 中也设置documentdomain,而且这也是必须的,虽然这个文档的domain就是examplecom,但是还是必须显示的设置documentdomain的值:

这样我们就可以通过js访问到iframe中的各种属性和对象了。

不过如果你想在http://wwwexamplecom/ahtml 页面中通过ajax直接请求http://examplecom/bhtml 页面,即使你设置了相同的documentdomain也还是不行的,所以修改documentdomain的方法只适用于不同子域的框架间的交互。如果你想通过ajax的方法去与不同子域的页面交互,除了使用jsonp的方法外,还可以用一个隐藏的iframe来做一个代理。原理就是让这个iframe载入一个与你想要通过ajax获取数据的目标页面处在相同的域的页面,所以这个iframe中的页面是可以正常使用ajax去获取你要的数据的,然后就是通过我们刚刚讲得修改documentdomain的方法,让我们能通过js完全控制这个iframe,这样我们就可以让iframe去发送ajax请求,然后收到的数据我们也可以获得了。

3、使用windowname来进行跨域

window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个windowname的,每个页面对windowname都有读写的权限,windowname是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。

比如:有一个页面ahtml,它里面有这样的代码:

再看看bhtml页面的代码:

ahtml页面载入后3秒,跳转到了bhtml页面,结果为:

我们看到在bhtml页面上成功获取到了它的上一个页面ahtml给windowname设置的值。如果在之后所有载入的页面都没对windowname进行修改的话,那么所有这些页面获取到的windowname的值都是ahtml页面设置的那个值。当然,如果有需要,其中的任何一个页面都可以对windowname的值进行修改。注意,windowname的值只能是字符串的形式,这个字符串的大小最大能允许2M左右甚至更大的一个容量,具体取决于不同的浏览器,但一般是够用了。

上面的例子中,我们用到的页面ahtml和bhtml是处于同一个域的,但是即使ahtml与bhtml处于不同的域中,上述结论同样是适用的,这也正是利用windowname进行跨域的原理。

下面就来看一看具体是怎么样通过windowname来跨域获取数据的。还是举例说明。

比如有一个wwwexamplecom/ahtml页面,需要通过ahtml页面里的js来获取另一个位于不同域上的页面wwwcnblogscom/datahtml里的数据。

datahtml页面里的代码很简单,就是给当前的windowname设置一个ahtml页面想要得到的数据值。datahtml里的代码:

那么在ahtml页面中,我们怎么把datahtml页面载入进来呢?显然我们不能直接在ahtml页面中通过改变windowlocation来载入datahtml页面,因为我们想要即使ahtml页面不跳转也能得到datahtml里的数据。答案就是在ahtml页面中使用一个隐藏的iframe来充当一个中间人角色,由iframe去获取datahtml的数据,然后ahtml再去得到iframe获取到的数据。

充当中间人的iframe想要获取到datahtml的通过windowname设置的数据,只需要把这个iframe的src设为wwwcnblogscom/datahtml就行了。然后ahtml想要得到iframe所获取到的数据,也就是想要得到iframe的windowname的值,还必须把这个iframe的src设成跟ahtml页面同一个域才行,不然根据前面讲的同源策略,ahtml是不能访问到iframe里的windowname属性的。这就是整个跨域过程。

看下ahtml页面的代码:

上面的代码只是最简单的原理演示代码,你可以对使用js封装上面的过程,比如动态的创建iframe,动态的注册各种事件等等,当然为了安全,获取完数据后,还可以销毁作为代理的iframe。网上也有很多类似的现成代码,有兴趣的可以去找一下。

通过windowname来进行跨域,就是这样子的。

4、使用HTML5中新引进的windowpostMessage方法来跨域传送数据

windowpostMessage(message,targetOrigin)  方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持windowpostMessage方法。

调用postMessage方法的window对象是指要接收消息的那一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符   。

需要接收消息的window对象,可是通过监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。

上面所说的向其他window对象发送消息,其实就是指一个页面有几个框架的那种情况,因为每一个框架都有一个window对象。在讨论第二种方法的时候,我们说过,不同域的框架间是可以获取到对方的window对象的,而且也可以使用windowpostMessage这个方法。下面看一个简单的示例,有两个页面

我们运行a页面后得到的结果:

我们看到b页面成功的收到了消息。

使用postMessage来跨域传送数据还是比较直观和方便的,但是缺点是IE6、IE7不支持,所以用不用还得根据实际需要来决定。

结语:

除了以上几种方法外,还有flash、在服务器上设置代理页面等跨域方式,这里就不做介绍了。

以上四种方法,可以根据项目的实际情况来进行选择应用,个人认为windowname的方法既不复杂,也能兼容到几乎所有浏览器,这真是极好的一种跨域方法。

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

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

在用vue做前端开发的时候,因为一般跑vue使用的webpack自带的node服务,而我们实际要使用的数据确是后台服务器上的,所以这就涉及到服务器请求跨域的问题。本来在诸如axios之类的网络请求参数里面配置

withCredentials: true,

就可以解决跨域问题的,但是现在浏览器比如chorme有做了新的跨域限制,比如要服务器端配置允许跨域才行,详见跨域问题解决,是英文的,看起来需要花点功夫;那有没有不需要服务器端配置就能解决浏览器的跨域问题的办法呢?答案肯定是有的!!

这里就说chorme吧,因为chorme基本都是前端主流浏览器了,配置方法如下:

版本号49之前的跨域设置

具体做法为:

1下载并安装好chorme浏览器后在桌面找到浏览器快捷图标并点击鼠标右键的属性一栏。

2在属性页面中的目标输入框里加上 --disable-web-security 如下图所示:

3点击应用和确定后关闭属性页面,并打开chrome浏览器。如果浏览器出现提示“你使用的是不受支持的命令标记 --disable-web-security”,那么说明配置成功。

版本号49之后的chrome跨域设置

chrome的版本升到49之后,跨域设置比以前严格了,在打开命令上加--disable-web-security之后还需要给出新的用户个人信息的目录。众所周知chrome是需要用gmail地址登录的浏览器,登录后就会生成一个存储个人信息的目录,保存用户的收藏、历史记录等个人信息。49版本之后,如果设置chrome浏览器为支持跨域模式,需要指定出一个个人信息目录,而不能使用默认的目录,估计是chrome浏览器怕用户勿使用跨域模式泄露自己的个人信息(主要是cookie,很多网站的登录token信息都是保存在cookie里)。

具体做法为:

1在电脑上新建一个目录,例如:C:\MyChromeDevUserData

2在属性页面中的目标输入框里加上 --disable-web-security --user-data-dir=C:\MyChromeDevUserData,--user-data-dir的值就是刚才新建的目录。

3点击应用和确定后关闭属性页面,并打开chrome浏览器。

再次打开chrome,发现有“--disable-web-security”相关的提示,说明chrome又能正常跨域工作了。

跨域成功后,首页换成了google的welcome页面,同时原来收藏的链接和历史记录都不见了,而C:\MyChromeDevUserData目录下则生成了新的个人信息相关的文件。

这样就解决了诸如

报错的问题,一个坑给填满了,后面还有很多坑需要去填,哈哈!!!

可以使用服务器代理或者在后端设置允许跨域。

现在的项目一般是在后端设置允许跨域,前端在带有允许跨域的情况下,可以像没有跨域一样正常访问。

如果前端单独发布到服务器,也可以在服务器是设置代理,使用代理转发请求。

要看服务器类型,如果服务器是apache

(1)修改http服务的配置文件:C:\wamp\bin\apache\Apache244\conf\httpdconf

把LoadModule headers_module modules/mod_headersso 前面的注释删除

(2)添加Header set Access-Control-Allow-Origin

<Directory />

AllowOverride none

Require all granted

Header set Access-Control-Allow-Origin

</Directory>

(3)重启http服务

如果是tomcat,比如spring MVC项目

创建一个过滤器,代码如下:

Java代码 收藏代码

package comwebfilter;

import javaioIOException;

import javaxservletFilter;

import javaxservletFilterChain;

import javaxservletFilterConfig;

import javaxservletServletException;

import javaxservletServletRequest;

import javaxservletServletResponse;

import javaxservlethttpHttpServletResponse;

import comcommondictConstant2;

import oaserviceDictionaryParam;

public class SimpleCORSFilter implements Filter{

@Override

public void destroy() {

}

@Override

public void doFilter(ServletRequest req, ServletResponse res,

FilterChain chain) throws IOException, ServletException {

HttpServletResponse response = (HttpServletResponse) res;

responsesetHeader("Access-Control-Allow-Origin", DictionaryParamget(Constant2DICTIONARY_GROUP_GLOBAL_SETTING, "AccessControlAllowOrigin"));

responsesetHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");

responsesetHeader("Access-Control-Max-Age", "3600");

responsesetHeader("Access-Control-Allow-Headers", "x-requested-with");

chaindoFilter(req, res);

}

@Override

public void init(FilterConfig arg0) throws ServletException {

}

}

关键代码:responsesetHeader("Access-Control-Allow-Origin", "");

<filter>

<filter-name>cors</filter-name>

<filter-class>comwebfilterSimpleCORSFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>cors</filter-name>

<url-pattern>/</url-pattern>

</filter-mapping>

这样服务器就支持ajax的跨域访问了

DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
网站模板库 » 我的一个java请求,该如何设置,别人就可以跨域访问我的请求得到数据

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情