跨域问题解决方案(HttpClient安全跨域 & jsonp跨域)

女爷i 2022-06-06 09:52 490阅读 0赞

1 错误场景

  1. 今天要把项目部署到外网的时候,出现了这样的问题, 我把两个项目放到自己本机的tomcat下, 进行代码调试, 运行

都没有问题的, 一旦把我需要调用接口的项目B放到其他的服务器上, 就会报错, 无法通过Ajax调用springMVC的接口,

这是什么原因呢?

  1. 当我使用json ajax post请求传递数据的时候在web端出错:XMLHttpRequest cannot load[http://ip:8082/security/auth/outside.do][http_ip_8082_security_auth_outside.do]. Origin [http://ip:8080][http_ip_8080] is not allowed by Access-Control-Allow-Origin.

2 初识jsonp

  1. 经过在网上查找, 网上大多数说是跨域问题. 解决跨域问题据说是jsonp, 百度了一篇文章, 不管三七二十一就一下

子把ajax传递的数据类型dataType 改成为jsonp, 并使用get方式, 单纯的认为, json和jsonp没啥区别, 运行, 报错, 如

下图所示:

Center

  1. 没有了上述的 is not allowed ....的错误, 变成了只剩下500的错误, 说明jsonp起了些作用, 我的bug的问题就是在于网上说的"跨域" 。而究竟什么是跨域呢?

3 什么是跨域?什么是不跨域?

  1. 上没有过多的去测试,一句话:同一个ip、同一个网络协议、同一个端口,三者都满足就是同一个域,否则就是

跨域问题了。而为什么开发者最初不直接定为一切可跨域的呢?默认的为什么都是不可跨域呢?这就涉及到了同源策

略,为了系统的安全,由Netscape提出一个著名的安全策略。现在所有支持JavaScript的浏览器都会使用这个策略。

所谓同源是,域名,协议,端口相同。当我们在浏览器中打开百度和谷歌两个网站时,百度浏览器在执行一个脚本的

时候会检查这个脚本属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行,如果没有同源策略,那

随便的向百度中注入一个js脚本,弹个恶意广告,通过js窃取信息,这就很不安全了。

4 跨域问题如何解决?jsonp为什么能解决跨域问题?和json有什么区别?

  1. 关于解决跨域问题,有多种解决方案,解决方案如下。
  2. 4.1 方案一
  3. ajax请求地址改为自己系统的后台地址,之后在自己的后台用HttpClient请求url。封装好的跨域请求url工具类

代码如下所示。

  1. @SuppressWarnings(“all”)
  2. public final class UrlUtil {
  3. private static HttpClient httpClient = new HttpClient();
  4. /**
  5. * @Title: getDataFromURL
  6. * @Description: 根据URL跨域获取输出结果,支持http
  7. * @param strURL
  8. * 要访问的URL地址
  9. * @param param
  10. * 参数
  11. * @return 结果字符串
  12. * @throws Exception
  13. */
  14. public static String getDataFromURL(String strURL, Map param) throws Exception {
  15. URL url = new URL(strURL);
  16. URLConnection conn = url.openConnection();
  17. conn.setDoOutput(true);
  18. OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
  19. final StringBuilder sb = new StringBuilder(param.size() << 4); // 4次方
  20. final Set keys = param.keySet();
  21. for (final String key : keys) {
  22. final String value = param.get(key);
  23. sb.append(key); // 不能包含特殊字符
  24. sb.append(‘=’);
  25. sb.append(value);
  26. sb.append(‘&’);
  27. }
  28. // 将最后的 ‘&’ 去掉
  29. sb.deleteCharAt(sb.length() - 1);
  30. writer.write(sb.toString());
  31. writer.flush();
  32. writer.close();
  33. InputStreamReader reder = new InputStreamReader(conn.getInputStream(), “utf-8”);
  34. BufferedReader breader = new BufferedReader(reder);
  35. // BufferedWriter w = new BufferedWriter(new FileWriter(“d:/1.txt”));
  36. String content = null;
  37. String result = null;
  38. while ((content = breader.readLine()) != null) {
  39. result += content;
  40. }
  41. return result;
  42. }
  43. /**
  44. * @Title: postMethod
  45. * @Description: 根据URL跨域获取输出结果,支持https
  46. * @param url
  47. * 要访问的URL地址(http://www.xxx.com?)
  48. * @param urlParm
  49. * 参数(id=1212&pwd=2332)
  50. * @return 结果字符串
  51. */
  52. public static String postMethod(String url, String urlParm) {
  53. if (null == url || “”.equals(url)) {
  54. // url = “http://www.baidu.com“;
  55. return null;
  56. }
  57. PostMethod post = new PostMethod(url); // new UTF8PostMethod(url);
  58. if (null != urlParm && !””.equals(urlParm)) {
  59. String[] arr = urlParm.split(“&”);
  60. NameValuePair[] data = new NameValuePair[arr.length];
  61. for (int i = 0; i < arr.length; i++) {
  62. String name = arr[i].substring(0, arr[i].lastIndexOf(“=”));
  63. String value = arr[i].substring(arr[i].lastIndexOf(“=”) + 1);
  64. data[i] = new NameValuePair(name, value);
  65. }
  66. post.setRequestBody(data);
  67. }
  68. int statusCode = 0;
  69. String pageContent = “”;
  70. try {
  71. statusCode = httpClient.executeMethod(post);
  72. if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
  73. pageContent = post.getResponseBodyAsString();
  74. return pageContent;
  75. }
  76. } catch (Exception e) {
  77. e.printStackTrace();
  78. return null;
  79. } finally {
  80. post.releaseConnection();
  81. }
  82. return null;
  83. }
  84. public static String doPost(String url, String json) throws Exception {
  85. PostMethod postMethod = new PostMethod(url);
  86. StringRequestEntity requestEntity = new StringRequestEntity(json, “application/json”, “UTF-8”);
  87. postMethod.setRequestEntity(requestEntity);
  88. /* 发送请求,并获取响应对象 */
  89. int statusCode = httpClient.executeMethod(postMethod);
  90. String result = null;
  91. if (statusCode == HttpStatus.SC_OK) {
  92. result = postMethod.getResponseBodyAsString();
  93. } else {
  94. System.out.println(“Method failed: “ + postMethod.getStatusLine());
  95. }
  96. return result;
  97. }
  98. public static String post(String url, Map params) {
  99. DefaultHttpClient httpclient = new DefaultHttpClient();
  100. String body = null;
  101. HttpPost post = postForm(url, params);
  102. body = invoke(httpclient, post);
  103. httpclient.getConnectionManager().shutdown();
  104. return body;
  105. }
  106. private static HttpPost postForm(String url, Map params) {
  107. HttpPost httpost = new HttpPost(url);
  108. List nvps = new ArrayList();
  109. Set keySet = params.keySet();
  110. for (String key : keySet) {
  111. BasicNameValuePair basicNameValuePair = new BasicNameValuePair(key, params.get(key));
  112. nvps.add(basicNameValuePair);
  113. }
  114. try {
  115. httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
  116. } catch (UnsupportedEncodingException e) {
  117. e.printStackTrace();
  118. }
  119. return httpost;
  120. }
  121. private static String invoke(DefaultHttpClient httpclient, HttpUriRequest httpost) {
  122. HttpResponse response = sendRequest(httpclient, httpost);
  123. String body = paseResponse(response);
  124. return body;
  125. }
  126. private static HttpResponse sendRequest(DefaultHttpClient httpclient, HttpUriRequest httpost) {
  127. HttpResponse response = null;
  128. try {
  129. response = httpclient.execute(httpost);
  130. } catch (Exception e) {
  131. e.printStackTrace();
  132. }
  133. return response;
  134. }
  135. private static String paseResponse(HttpResponse response) {
  136. HttpEntity entity = response.getEntity();
  137. String body = null;
  138. try {
  139. body = EntityUtils.toString(entity);
  140. } catch (Exception e) {
  141. e.printStackTrace();
  142. }
  143. return body;
  144. }
  145. public static void main(String[] args) throws Exception {
  146. String url = “http://ip:8082/security/auth/outside.do“;
  147. Map map = new HashMap();
  148. map.put(“loginName”, “root”);
  149. map.put(“code”, “vms2.0”);
  150. String msg = post(url, map);
  151. JSONArray jary = JsonUtil.Json2JSONArray(msg);
  152. for (int i = 0; i < jary.length(); i++) {
  153. JSONObject obj = jary.getJSONObject(i);
  154. System.out.println(obj);
  155. // System.out.print(obj.getString(“classid”));
  156. // System.out.print(“\t”+obj.getString(“classname”));
  157. // System.out.println(“\t”+obj.getString(“sonclass”));
  158. }
  159. // System.out.println(jary);
  160. }
  161. }
  1. 当然要导入httpclient-4.3.1.jar包到自己的项目中哦。这样把请求的参数内容放到map中,通过HttpClent来实现跨域请求。
  2. 4.2 解决方案二
  3. 两个系统之间的数据传递是通过ajax post请求,传递json的方式来完成,我们在这里可以使用jsonp的方式,但

是json和jsonp截然不同。首先说说神马是json,再说神马是jsonp。

json

  1. 全拼(javaScript Object Notation)轻量级的数据交换格式,易于机器解析和生成。基于javaScript

Programming Language,StandardECMA Edition December1999的一个子集。json完全独立于语言的文本格

式,但是也使用类似于C语言家族的习惯(include c c++ c# java javaScript perl python)等,这些特性使得json

成为理想的数据交换语言。格式为key,value格式,具体就不赘述了。

jsonp

  1. jsonp全拼是(json with Padding)是json的一种使用模式,padding意思为填料,垫料,填充,填补。json

以说是名词,而jsonp是动宾短语,两者有联系,但是有本质的区别,就像米饭和把米饭填充到碗里一样,那米饭和

米饭填是一样的么,我们自然明了了。

  1. jsonp算是钻空子实现的跨域,到底通过jsonp具体如何解决跨域问题呢?本篇过长了,我们下篇分晓。goodnight...

本篇文章主要是对使用jQuery与JSONP轻松解决跨域访问的问题进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助

时间过得好快,又被拉回js战场时, 跨域问题这个伤疤又开疼了.

好在,有jquery帮忙,跨域问题似乎没那么难缠了.这次也借此机会对跨域问题来给刨根问底,结合实际的开发项目,查阅了相关资料,算是解决了跨域问题..有必要记下来备忘.

跨域的安全限制都是指浏览器端来说的.服务器端是不存在跨域安全限制的,所以通过本机服务器端通过类似httpclient方式完成“跨域访问”的工作,然后在浏览器端用AJAX获取本机服务器端“跨域访问”对应的url.来间接完成跨域访问也是可以的.但很显然开发量比较大,但限制也最少,很多widget开放平台server端(如sohu博客开放平台)其实就么搞的.不在本次讨论范围.

要讨论的是浏览器端的真正跨域访问,推荐的是目前jQuery $.ajax()支持get方式的跨域,这其实是采用jsonp的方式来完成的.

真实案例:

复制代码代码如下:

var qsData = {‘searchWord’:$(“#searchWord”).attr(“value”),’currentUserId’:$(“#currentUserId”).attr(“value”),’conditionBean.pageSize’:$(“#pageSize”).attr(“value”)};

$.ajax({
async:false,
url: http://跨域的dns/document!searchJSONResult.action,
type: “GET”,
dataType: ‘jsonp’,
jsonp: ‘jsoncallback’,
data: qsData,
timeout: 5000,
beforeSend: function(){
//jsonp 方式此方法不被触发.原因可能是dataType如果指定为jsonp的话,就已经不是ajax事件了
},
success: function (json) {//客户端jquery预先定义好的callback函数,成功获取跨域服务器上的json数据后,会动态执行这个callback函数
if(json.actionErrors.length!=0){
alert(json.actionErrors);
}
genDynamicContent(qsData,type,json);
},
complete: function(XMLHttpRequest, textStatus){
$.unblockUI({ fadeOut: 10 });
},
error: function(xhr){
//jsonp 方式此方法不被触发.原因可能是dataType如果指定为jsonp的话,就已经不是ajax事件了
//请求出错处理
alert(“请求出错(请检查相关度网络状况.)”);
}
});

注意:

复制代码代码如下:

$.getJSON(“ http://跨域的dns/document!searchJSONResult.action?name1="+value1+"&jsoncallback=?“,
function(json){
if(json.属性名==值){
// 执行代码
}
});

这种方式其实是上例$.ajax({..}) api的一种高级封装,有些$.ajax api底层的参数就被封装而不可见了.
这样,jquery就会拼装成如下的url get请求
http://跨域的dns/document!searchJSONResult.action?&jsoncallback=jsonp1236827957501&\_=1236828192549&searchWord=%E7%94%A8%E4%BE%8B¤tUserId=5351&conditionBean.pageSize=15

在响应端(http://跨域的dns/document!searchJSONResult.action),
通过 jsoncallback = request.getParameter(“jsoncallback”) 得到jquery端随后要回调的js function name:jsonp1236827957501
然后 response的内容为一个Script Tags:”jsonp1236827957501(“+按请求参数生成的json数组+”)”;
jquery就会通过回调方法动态加载调用这个js tag:jsonp1236827957501(json数组);
这样就达到了跨域数据交换的目的.

jsonp的最基本的原理是:动态添加一个

发表评论

表情:
评论列表 (有 0 条评论,490人围观)

还没有评论,来说两句吧...

相关阅读

    相关 jsonp

    首先我们来说说什么是跨域       跨域:是指从一个域名的网页去请求另一个域名的资源。比如从www.baidu.com 页面去请求 www.google.com 的资源。但

    相关 jsonp

    我是做的一个跨站显示信息!! 鄙人文化不高,代码不严谨,仅供参考! 题目:用户在a站访问过的商品足迹可以在登录b站之后查看足迹! 首先创建两个域名www.a.com

    相关 jsonp

    jsonp跨域 Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src这个属性的标签都拥有跨域的能力,比如`<script>、<img>、<

    相关 JSONP和CORS

    什么是跨域? 跨域:指的是浏览器不能执行其它网站的脚本,它是由浏览器的同源策略造成的,是浏览器的安全限制! 同源策略 同源策略:域名、协议、端口均相同。 浏览器

    相关 jsonp

    域指的就是域名。 域名对应的是一个IP地址。 域名与IP地址的对应关系存储在域名服务器上。(DNS)   所谓跨域     1.就是跨域名,跨端口,跨协议