Ⅰ javahttpclient post请求 x-forwarded-for这个可以设置成其他ip么
目前,要为另一个项目提供接口,接口是用HTTP URL实现的,最初的想法是另一个项目用内jQuery post进行容请求。
但是,很可能另一个项目是部署在别的机器上,那么就存在跨域问题,而jquery的post请求是不允许跨域的。
这时,就只能够用HttpClient包进行请求了,同时由于请求的URL是HTTPS的,为了避免需要证书,所以用一个类继承DefaultHttpClient类,忽略校验过程。
写一个SSLClient类,继承至HttpClient。
Ⅱ java为什么会有跨域问题
前言
相信大家在写前端脚本的时候经常会遇到发送数据到后台的情况,但是由于浏览器的限制,不同域名之间的数据是不能互相访问的,那前端怎么和后端如何进行数据之间的交换呢?
JavaScript由于安全性方面的考虑,不允许页面跨域调用其他页面的对象,那么问题来了,什么是跨域问题?
答:这是由于浏览器同源策略的限制,现在所有支持JavaScript的浏览器都使用了这个策略。那么什么是同源呢?所谓的同源是指三个方面“相同”:
域名相同
协议相同
端口相同
下面就举几个例子来帮助更好的理解同源策略。
URL
说明
是否允许通信
http://www.a.com/a.js
http://www.a.com/b.js 同一域名 允许
http://www.a.com/a.js
http://www.b.com/a.js 不同域名 不允许
http://www.a.com:8000/a.js
http://www.a.com/b.js 同一域名不同端口 不允许
https://www.a.com/a.js
http://www.a.com/b.js 同一域名不同协议 不允许
在JAVA中处理跨域问题,通常有以下两种常用的解决方法。
第一种解决方法
后台代码在被请求的Servlet中添加Header设置:
Access-Control-Allow-Origin这个Header在W3C标准里用来检查该跨域请求是否可以被通过,如果值为*则表明当前页面可以跨域访问。默认的情况下是不允许的。
在前端JS中需要向Servlet发出请求,请求代码如下所示:
第二种解决方法
通过jsonp跨域请求的方式。JSONP和JSON虽然只有一个字母的区别,但是他们完全就是两回事,很多人很容易把他们搞混。JSON是一种数据交换的格式,而JSONP则是一种非官方跨域数据交互协议。
首先来说一下前端JS是怎么发送请求。代码如下所示:
这里的callbackparam和success_jsonpCallback可以理解为发送的data数据的键值对,可以自定义,但是callbackparam需要和后台约定好参数名称,因为后台需要获取到这个参数里面的值(即success_jsonpCallback)。
下面,最重要的来了,后台怎么样获取和返回数据呢。代码如下所示:
首先需要获取参数名为callbackparam的值,这里获取到的值就是“success_jsonpCallback”。然后将这个值加上一对小括号。小括号里放入你需要返回的数据内容,比如这里我返回一个JSON对象。当然你也可以返回其他对象,比如只返回一个字符串类型数据也可以。最后前端JS返回的数据就是这样的:
浏览器会自动解析为json对象,这时候你只需要在success回调函数中直接用data.status就可以了。
Ⅲ 后端允许跨域怎么设置(后端配置允许跨域无效)
跨域的几种方法浏览器出于安全方面的考虑,只允许客户端与本域(同协议、同域名、同端口,三者缺一不可)下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源,这被称为同源策略。
而有时候,我们不得不在一个客户端下访问不同域中的资源,于是需要用到一些方法来避开浏览器的同源策略,这些方法被称为跨域。
实现跨域有如下几种方法:
JSONP(JSONwithPadding)是数据格式JSON的一种使用模式,可以使网页实现跨域请求。其原理主要利用了HTML的script标签。由于script是采用开放策略,通过设置src引入不同域下的资源,所以可以通过script实现跨域,该方法需要后端支持。jsonp跨域的实现步骤如下:
下面来做个演示,首先为演示方便,将系统的hosts做如下修改:
以上例子最终实现了由example.a.com到example.b.com的跨域。应注意的是,因为script只能发送GET请求,所以jsonp只能实现GET请求的跨域。如果希望能实现其他请求的跨域,就可以用接下来介绍的一种方法——CORS。
CORS(全称为:Cross-OriginResouceSharing)跨域资源共享,是一种通过ajax跨域请求资源的方法。浏览器将CORS请求分为两大类,简单请求(simplerequest)和非简单请求(not-so-simplerequest,浏览器对这两种请求的处理方式不一样。如果请求满足以下两个条件,则为简单请求。
简单请求的实现方式即当用XMLHttpRequest发请求时,浏览器如果发现该请求不符合同源策略,会给该请求加上一个请求头origin,origin用来说明本次请求来自哪个源(协议+域名+端口)。如果origin指定的源不在后台允许范围内,后台会返回一个正常的HTTP响应,然后浏览器会发现该响应头部信息不包含Access-Control-Allow-Origin字段,然后抛出一个错误,该错误被XMLHttpRequest的onerror函数捕获,响应被驳回,但因为该错误无法通过状态码识别,所以HTTP回应的状态码还是200。如果origin在后台允许范围内,则服务器返回的响应,会包含Access-Control-Allow-Origin:Origin(指定的源)信息,浏览器此时不会抛错,响应能正常处理。
非简单请求是是请求方法为PUT或DELETE,又或者Content-Type为application/json的对服务器有特殊要求的请求。非简单请求的CORS请求,会在正式通信前增加一次HTTP查询,称为预检(preflight),询问服务器当前网页所在域名是否在服务器的许可名单中,如果在,则发出正式的XMLHttpRequest,之后就与简单请求一样,不在则报错。
依旧用上面的例子。
最终实现的效果与第一个jsonp的例子一样。
还有一种方式,就是通过降域来实现跨域。即通过设置document.domain的方式,将两个域名的domain设置为一个,如对于a.example.com和b.example.com,可以通过js设置document.domain="example.com",实现跨域。
做个演示,假设在下有一个a.html文件,其中a.html中有一个iframe,它的src为。
用降域方法实现跨域操作简单,但是有一些缺点。比如域名只能往下设置,不能回去,比如从example.com回到a.example.com。同时如果一个子域名被攻击,多个被降域的域名都会被连带攻击,有很大的安全风险。
postMessage是一个webAPI,可以实现跨域通信。window.postMessage()被调用时,会在所有页面脚本执行完毕后,向目标窗口派发一个MessageEvent消息。语法如下:
MessageEvent具有如下属性:
用一个与上面降域类似的例子来做演示。同样有两个页面a.html和b.html,a.html中的iframe的src指向b.html。
最终实现a.html与b.html通信效果如下:
使用postMessage方法应注意的是,如果不希望从其他网站接收message,那么不要为message事件添加任何监听器。如果确实希望接收其他网站的message,那么应该始终使用origin和source属性来验证发件人的身份,以免被恶意的网站攻击。
以上就是几种常见的跨域方法,各有优劣,且各自都有一定的安全问题,在日常应用中,需要有针对性的使用,对可能的安全风险采取相应措施。
前后端联调——跨域问题
19.7.24
前端通过http请求跨域的同时需要带上cookie信息,前端需要设置withCredentials=true。
而后端也需要有所修改。
Access-Control-Allow-Origin字段必须指定域名,不能为*
Access-Control-Allow-Credentials为true
后端可以通过HtttpServletRequest的Header中找到Origin。是跨域地址的host加port。
后端需要维护一个跨域URL的白名单,用Origincontains匹配白名单的URL,成功则配置response的Access-Control-Allow-Origin,指定Origin。
就实现跨域传cookie了。
参考:
什么是跨域、怎么解决跨域?一个请求url的**协议、端口、域名**其中任意一个与当前页面url不相同就是跨域
即:?(http/https)协议、(segmentfault)主域名、(www)子域名、(8080)端口
是因为浏览器的同源策略的限制,同源策略是一种安全策略,同源指的是域名,协议,端口相同,会阻止一个域的js脚本和另一个域的内容进行交互。防止在一个浏览器中的两个页面产生不安全、异常的行为。
当然如果不同源的话会产生一定的限制:
【1】无法读取非同源网页的Cookie、LocalStorage和IndexedDB
【2】无法接触非同源网页的DOM
【3】无法向非同源地址发送AJAX请求
document.createElement(‘script’)生成一个script标签,然后插body里而已。
JSONP的实现原理就是创建一个script标签,再把需要请求的api地址放到src里.这个请求只能用GET方法,不可能是POST(向服务端传送数据)。
一种非正式传输协议,它会允许用户传递一个callback参数给服务端,然后服务端返回数据的时候会将这个callback参数作为函数名来包裹住JSON数据,然后客户端就可以随意的定义自己的函数来处理返回的数据了。
一般是后端在处理请求数据的时候,添加允许跨域的请求头信息,服务端设置Access-Control-Allow-Origin就可以,如果需要携带cookie,前后端都需要设置
window对象有个name的属性,在一个window下,窗口载入的页面都是共享一个window.name。
在a.html中,怎么把b.html页面加载进来,获取b.html的数据。在a.html页面使用iframe,可以去获取b.html的数据,然后在a.html页面中取得iframe获取得数据。
但是iframe想要获取b.html中的数据,只需要给这个iframe的src设为就可以,如果a.html想要得到iframe所获得的数据,也就是iframe的window.name的值,还要把这个iframe的src设成跟a.html页面同一个域才可以,不然a.html访问不到iframe里的window.name属性。
//父窗口打开一个子窗口
??varopenWindow=window.open('','title');
//父窗口向子窗口发消息(第一个参数代表发送的内容,第二个参数代表接收消息窗口的url)
??openWindow.postMessage('Nicetomeetyou!','');
调用message事件,监听对方发送的消息
//监听message消息
??window.addEventListener('message',function(e){
??console.log(e.source);//e.source发送消息的窗口
??console.log(e.origin);//e.origin消息发向的网址
??console.log(e.data);?//e.data?发送的消息
??},false);
??server{
??#监听9099端口
??listen9099;
??#域名是localhost
??server_namelocalhost;
??#凡是localhost:9099/api这个样子的,都转发到真正的服务端地址
??location^~/api{
????proxy_pass;
??}??
?}
//请求的时候直接用回前端这边的域名,这就不会跨域,然后Nginx监听到凡是localhost:9099/api这个样子的,都转发到真正的服务端地址
fetch('',{
?method:'POST',
?headers:{
??'Accept':'application/json',
??'Content-Type':'application/json'
?},
?body:JSON.stringify({
??msg:'helloIframePost'
?})
})
关于跨域的问题一、在前端开发过程中,如果准备开发富应用,跨域的问题将会随之而来。
????????我们先看看什么是跨域呢:
????????所谓跨域,或者异源,是指主机名(域名)、协议、端口号只要有其一不同,就为不同的域(或源)。出于保护用户数据的目的,浏览器有一个最基本的策略就是同源策略,只允许页面内的脚本访问当前域的资源(加载脚本、资源等不受此限制)。
二、如果浏览器厂商不对跨域请求进行处理,会给我们带来什么危害呢?
????有心人士(病毒制造者)会利用这个漏洞进行如下攻击:
????1.CSRF/XSRF攻击,简单的来讲就是在b.com页面中请求a.com的接口(浏览器会自动带上用户在a.com的cookie),从而获取用户的在a.com的相关信息。
????2.XSS注入攻击,类似于SQL攻击,提交含有恶意脚本的数据到服务器,从而达到破坏页面或者获取用户的cookie。
三、我们了解到了什么是跨域,那我们又应该如何解决呢,现在找到了这些比较权威的文章,大家先品读一下:
????????1.mozilla官方网站关于跨域的文章(CrossOrigin),HTTP访问控制(CORS)
????????2.mozilla官方网站关于浏览器同源策略的简要介绍(SameOrigin),?浏览器的同源策略
四、读完这些文章,你打算怎么处理跨域问题呢,我先谈谈自己关于跨域的解决方案:
????????1.采用CORS协议,直接在Nginx中设置允许跨域的header(也可以在后端的应用程序内设置,不过在Nginx入口配置的话更加统一),在location配置中直接使用指令add_header(官方文档链接),示例配置如下:
????????2.使用JSONP,也是需要后端配合,利用“浏览器加载脚本、资源时不受同源策略的约束”这个特性,但是这种方式非常受限制,例如只能使用GET请求,不能携带自定义header等。
????3.其他的一些方法,例如window.name,document.domain以及HTML5中的特性window.postMessage等
五、其他参考链接
????1.?浅谈JS跨域问题
????2.跨域资源共享CORS详解----阮一峰
六、声明
????现在网络上的知识非常复杂,有些是摘自权威书籍的,有些是作者自己理解然后记录下来的,有些是瞎掰的,所以一定要结合情况多多甄别,对于有权威文档的知识点,建议先参考文档。
后端配置跨域原文连接:原文地址
跨域的详细介绍可以参考:浏览器和服务器实现跨域(CORS)判定的原理,这里不多赘述。
1、主要就是客户端向发送了服务端请求,服务器已经能返回数据,但是浏览器不接收
2、在接口里面加上:(因为request是处理请求,response是返回结果)
response.setHeader("Access-Control-Allow-Origin",?"*");
response.setHeader("Cache-Control","no-cache");?
3、如果是使用SpringBoot创建的项目,直接添加一句注解到controller和方法就可以了:
@CrossOrigin
其中@CrossOrigin中的2个参数:
origins?:允许可访问的域列表
maxAge:准备响应前的缓存持续的最大时间(以秒为单位)。
在这个例子中,对于retrieve()和remove()处理方法都启用了跨域支持,还可以看到如何使用@CrossOrigin属性定制CORS配置。如果同时使用controller和方法级别的CORS配置,Spring将合并两个注释属性以创建合并的CORS配置。
4、如果您正在使用SpringSecurity,请确保在Spring安全级别启用CORS,并允许它利用SpringMVC级别定义的配置。
二、全局CORS配置
除了细粒度、基于注释的配置之外,您还可能需要定义一些全局CORS配置。这类似于使用筛选器,但可以声明为SpringMVC并结合细粒度@CrossOrigin配置。默认情况下,所有originsandGET,HEADandPOSTmethods是允许的。
JavaConfig
使整个应用程序的CORS简化为:
更多使用请看原文连接和官方文档
后端解决前端跨域请求问题场景:前后端分离,页面和后端项目部署在不同服务器,出现请求跨域问题。
原因:CORS:跨来源资源共享(CORS)是一份浏览器技术的规范,提供了Web服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略,是JSONP模式的现代版。与JSONP不同,CORS除了GET要求方法以外也支持其他的HTTP要求。用CORS可以让网页设计师用一般的XMLHttpRequest,这种方式的错误处理比JSONP要来的好,JSONP对于RESTful的API来说,发送POST/PUT/DELET请求将成为问题,不利于接口的统一。但另一方面,JSONP可以在不支持CORS的老旧浏览器上运作。不过现代的浏览器(IE10以上)基本都支持CORS。
预检请求(option):在CORS中,可以使用OPTIONS方法发起一个预检请求(一般都是浏览检测到请求跨域时,会自动发起),以检测实际请求是否可以被服务器所接受。预检请求报文中的Access-Control-Request-Method首部字段告知服务器实际请求所使用的HTTP方法;Access-Control-Request-Headers首部字段告知服务器实际请求所携带的自定义首部字段。服务器基于从预检请求获得的信息来判断,是否接受接下来的实际请求。
解决方案:
1、创建一个过滤器,过滤options请求。
packagecom.biz.eisp.sci.util;
importorg.apache.commons.httpclient.HttpStatus;
importjavax.servlet.*;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjava.io.IOException;
/**
*解决跨域问题
*?
*/
{//filter接口的自定义实现
??publicvoidinit(FilterConfigfilterConfig)throwsServletException{
}
@Override
??publicvoiddoFilter(ServletRequestservletRequest,,FilterChainfilterChain)throwsIOException,ServletException{
HttpServletResponseresponse=(HttpServletResponse)servletResponse;
????HttpServletRequestrequest=(HttpServletRequest)servletRequest;
????response.setHeader("Access-Control-Allow-Origin","*");
????if("OPTIONS".equals(request.getMethod())){//这里通过判断请求的方法,判断此次是否是预检请求,如果是,立即返回一个204状态吗,标示,允许跨域;预检后,正式请求,这个方法参数就是我们设置的post了
??????response.setStatus(HttpStatus.SC_NO_CONTENT);//HttpStatus.SC_NO_CONTENT=204
??????response.setHeader("Access-Control-Allow-Methods","POST,GET,DELETE,OPTIONS,DELETE");//当判定为预检请求后,设定允许请求的方法
??????response.setHeader("Access-Control-Allow-Headers","Content-Type,x-requested-with");//当判定为预检请求后,设定允许请求的头部类型
??????response.addHeader("Access-Control-Max-Age","1");?//预检有效保持时间
????}
filterChain.doFilter(request,response);
??}
@Override
??publicvoiddestroy(){
}
}
2、修改web.xml文件
filter
?filter-namecors/filter-name
?filter-classcom.biz.eisp.sci.util.CorsFilter/filter-class
/filter
filter-mapping
filter-namecors/filter-name
?url-pattern/*?/url-pattern
/filter-mapping
3、spring-mvc.xml添加HttpRequestHandlerAdapter?http请求处理器适配器。
HttpRequestHandlerAdapter作为HTTP请求处理器适配器仅仅支持对HTTP请求处理器的适配。它简单的将HTTP请求对象和响应对象传递给HTTP请求处理器的实现,它并不需要返回值。它主要应用在基于HTTP的远程调用的实现上。
beanclass="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/