跨域问题解决方式(HttpClient安全跨域 & jsonp跨域)
1 错误场景
今天要把项目部署到外网的时候,出现了这种问题, 我把两个项目放到自己本机的tomcat下, 进行代码调试, 执行
都没有问题的, 一旦把我须要调用接口的项目B放到其它的server上, 就会报错, 无法通过Ajax调用springMVC的接口,
这是什么原因呢?
当我使用json ajax post请求传递数据的时候在web端出错:XMLHttpRequest cannot loadhttp://ip:8082/security/auth/outside.do.
Origin http://ip:8080 is not allowed by Access-Control-Allow-Origin.
2 初识jsonp
经过在网上查找, 网上大多数说是跨域问题. 解决跨域问题据说是jsonp, 百度了一篇文章, 无论三七二十一就一下
子把ajax传递的数据类型dataType 改成为jsonp, 并使用get方式, 单纯的觉得, json和jsonp没啥差别, 执行, 报错, 如
下图所看到的:
没有了上述的 is not allowed ....的错误, 变成了仅仅剩下500的错误, 说明jsonp起了些作用, 我的bug的问题就是在于网上说的"跨域" 。
而到底什么是跨域呢?
3 什么是跨域?什么是不跨域?
上没有过多的去測试,一句话:同一个ip、同一个网络协议、同一个port。三者都满足就是同一个域,否则就是
跨域问题了。
而为什么开发人员最初不直接定为一切可跨域的呢?默认的为什么都是不可跨域呢?这就涉及到了同源策
略,为了系统的安全,由Netscape提出一个著名的安全策略。
如今全部支持JavaScript的浏览器都会使用这个策略。
所谓同源是,域名。协议,port同样。当我们在浏览器中打开百度和谷歌两个站点时,百度浏览器在运行一个脚本的
时候会检查这个脚本属于哪个页面的。即检查是否同源,仅仅有和百度同源的脚本才会被运行,假设没有同源策略,那
随便的向百度中注入一个js脚本,弹个恶意广告,通过js窃取信息。这就非常不安全了。
4 跨域问题怎样解决?jsonp为什么能解决跨域问题?和json有什么差别?
关于解决跨域问题,有多种解决方式,解决方式例如以下。
4.1 方案一
ajax请求地址改为自己系统的后台地址,之后在自己的后台用HttpClient请求url。封装好的跨域请求url工具类
代码例如以下所看到的。
<span style="font-size:18px;">@SuppressWarnings("all")
public final class UrlUtil { private static HttpClient httpClient = new HttpClient(); /**
* @Title: getDataFromURL
* @Description: 依据URL跨域获取输出结果。支持http
* @param strURL
* 要訪问的URL地址
* @param param
* 參数
* @return 结果字符串
* @throws Exception
*/
public static String getDataFromURL(String strURL, Map<String, String> param) throws Exception {
URL url = new URL(strURL);
URLConnection conn = url.openConnection();
conn.setDoOutput(true); OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
final StringBuilder sb = new StringBuilder(param.size() << 4); // 4次方
final Set<String> keys = param.keySet();
for (final String key : keys) {
final String value = param.get(key);
sb.append(key); // 不能包括特殊字符
sb.append('=');
sb.append(value);
sb.append('&');
}
// 将最后的 '&' 去掉
sb.deleteCharAt(sb.length() - 1);
writer.write(sb.toString());
writer.flush();
writer.close(); InputStreamReader reder = new InputStreamReader(conn.getInputStream(), "utf-8");
BufferedReader breader = new BufferedReader(reder);
// BufferedWriter w = new BufferedWriter(new FileWriter("d:/1.txt"));
String content = null;
String result = null;
while ((content = breader.readLine()) != null) {
result += content;
} return result;
} /**
* @Title: postMethod
* @Description: 依据URL跨域获取输出结果。支持https
* @param url
* 要訪问的URL地址(http://www.xxx.com?)
* @param urlParm
* 參数(id=1212&pwd=2332)
* @return 结果字符串
*/
public static String postMethod(String url, String urlParm) {
if (null == url || "".equals(url)) {
// url = "http://www.baidu.com";
return null;
}
PostMethod post = new PostMethod(url); // new UTF8PostMethod(url);
if (null != urlParm && !"".equals(urlParm)) {
String[] arr = urlParm.split("&");
NameValuePair[] data = new NameValuePair[arr.length];
for (int i = 0; i < arr.length; i++) {
String name = arr[i].substring(0, arr[i].lastIndexOf("="));
String value = arr[i].substring(arr[i].lastIndexOf("=") + 1);
data[i] = new NameValuePair(name, value);
}
post.setRequestBody(data);
}
int statusCode = 0;
String pageContent = "";
try {
statusCode = httpClient.executeMethod(post);
if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
pageContent = post.getResponseBodyAsString();
return pageContent;
}
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
post.releaseConnection();
}
return null;
} public static String doPost(String url, String json) throws Exception {
PostMethod postMethod = new PostMethod(url);
StringRequestEntity requestEntity = new StringRequestEntity(json, "application/json", "UTF-8");
postMethod.setRequestEntity(requestEntity);
/* 发送请求,并获取响应对象 */
int statusCode = httpClient.executeMethod(postMethod);
String result = null;
if (statusCode == HttpStatus.SC_OK) {
result = postMethod.getResponseBodyAsString();
} else {
System.out.println("Method failed: " + postMethod.getStatusLine());
}
return result;
} public static String post(String url, Map<String, String> params) {
DefaultHttpClient httpclient = new DefaultHttpClient();
String body = null;
HttpPost post = postForm(url, params);
body = invoke(httpclient, post);
httpclient.getConnectionManager().shutdown();
return body;
} private static HttpPost postForm(String url, Map<String, String> params) {
HttpPost httpost = new HttpPost(url);
List<BasicNameValuePair> nvps = new ArrayList<BasicNameValuePair>();
Set<String> keySet = params.keySet();
for (String key : keySet) {
BasicNameValuePair basicNameValuePair = new BasicNameValuePair(key, params.get(key));
nvps.add(basicNameValuePair);
}
try {
httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return httpost;
} private static String invoke(DefaultHttpClient httpclient, HttpUriRequest httpost) {
HttpResponse response = sendRequest(httpclient, httpost);
String body = paseResponse(response);
return body;
} private static HttpResponse sendRequest(DefaultHttpClient httpclient, HttpUriRequest httpost) {
HttpResponse response = null;
try {
response = httpclient.execute(httpost);
} catch (Exception e) {
e.printStackTrace();
}
return response;
} private static String paseResponse(HttpResponse response) {
HttpEntity entity = response.getEntity();
String body = null;
try {
body = EntityUtils.toString(entity);
} catch (Exception e) {
e.printStackTrace();
}
return body;
} public static void main(String[] args) throws Exception {
String url = "http://ip:8082/security/auth/outside.do";
Map<String, String> map = new HashMap<String, String>();
map.put("loginName", "root");
map.put("code", "vms2.0");
String msg = post(url, map);
JSONArray jary = JsonUtil.Json2JSONArray(msg);
for (int i = 0; i < jary.length(); i++) {
JSONObject obj = jary.getJSONObject(i);
System.out.println(obj);
// System.out.print(obj.getString("classid"));
// System.out.print("\t"+obj.getString("classname"));
// System.out.println("\t"+obj.getString("sonclass"));
}
// System.out.println(jary);
}
}</span>
当然要导入httpclient-4.3.1.jar包到自己的项目中哦。这样把请求的參数内容放到map中。通过HttpClent来实现跨域请求。
4.2 解决方式二
两个系统之间的数据传递是通过ajax post请求,传递json的方式来完毕,我们在这里能够使用jsonp的方式。但
是json和jsonp截然不同。首先说说神马是json,再说神马是jsonp。
json
全拼(javaScript Object Notation)轻量级的数据交换格式,易于机器解析和生成。基于javaScript
Programming Language,StandardECMA Edition December1999的一个子集。json全然独立于语言的文本格
式,可是也使用类似于C语言家族的习惯(include c c++ c# java javaScript perl python)等。这些特性使得json
成为理想的数据交换语言。格式为key,value格式,详细就不赘述了。
jsonp
jsonp全拼是(json with Padding)是json的一种使用模式,padding意思为填料,垫料,填充,填补。json可
以说是名词,而jsonp是动宾短语,两者有联系,可是有本质的差别,就像米饭和把米饭填充到碗里一样,那米饭和
米饭填是一样的么,我们自然明了了。
jsonp算是钻空子实现的跨域,究竟通过jsonp详细怎样解决跨域问题呢?本篇过长了,我们下篇分晓。goodnight...
跨域问题解决方式(HttpClient安全跨域 & jsonp跨域)的更多相关文章
- 使用Httpclient来替代客户端的jsonp跨域解决方案
最近接手一个项目,新项目需要调用老项目的接口,但是老项目和新项目不再同一个域名下,所以必须进行跨域调用了,但是老项目又不能进行任何修改,所以jsonp也无法解决了,于是想到了使用了Httpclient ...
- AJAX跨域问题解决方法(4)——调用方解决跨域
调用方解决跨域的方法只有一种,那就是隐藏跨域. 何为隐藏跨域? 隐藏跨域的核心思路是通过反向代理隐藏跨域以欺骗浏览器 什么是反向代理?反向代理是指通过中间服务器使得访问同一个域名的两个不同url最终会 ...
- AJAX跨域问题解决方法(1)——禁止浏览器进行跨域限制
思路:通过命令行修改浏览器启动参数,使得浏览器不进行跨域检查,从而允许跨域 方法:命令行参数启动浏览器后添加参数--disable-web-security 例:chrome --disable-we ...
- 深入剖析jsonp跨域原理
在项目中遇到一个jsonp跨域的问题,于是仔细的研究了一番jsonp跨域的原理.搞明白了一些以前不是很懂的地方,比如: 1)jsonp跨域只能是get请求,而不能是post请求: 2)jsonp跨域的 ...
- 06: AJAX全套 & jsonp跨域AJAX
目录: 1.1 AJAX介绍 1.2 jQuery AJAX(第一种) 1.3 原生ajax(第二种) 1.4 iframe“伪”AJAX(第三种) 1.5 jsonp跨域请求 1.6 在tornad ...
- jquery ajax怎么使用jsonp跨域访问
在项目中使用接口的比较多,在客户端跨域访问,jquery中只能使用jquery ajax的jsonp方法. 值得注意的是,jQuery.ajax()只支持get方式的跨域,post的方式是不支持的.& ...
- 跨域问题解决方案(HttpClient安全跨域 & jsonp跨域)
1 错误场景 今天要把项目部署到外网的时候,出现了这样的问题, 我把两个项目放到自己本机的tomcat下, 进行代码调试, 运行 都没有问题的, 一旦把我需要调用接口的项目B放到其他的服务器上, 就会 ...
- JavaScript跨域解决方式
平时工作中经常被JavaScript跨域问题所困扰,其实有很多种解决方式,下面给大家介绍常用的几种: 1.jsonp解决跨域问题 客户端代码: <!DOCTYPE html> <ht ...
- 前端JavaScript实现跨域的方式(转)
这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...
随机推荐
- poj2914 Minimum Cut 全局最小割模板题
Minimum Cut Time Limit: 10000MS Memory Limit: 65536K Total Submissions: 8324 Accepted: 3488 Case ...
- mvc与mvp与mvvm
==MVC,MVP和MVVM都是常见的软件架构设计模式,它通过分离关注点来改进代码的组织方式== MVC.MVP和MVVM的相同点和不同点 不同部分是C(Controller).P(Presenter ...
- 0-Broadcast机制原理简要介绍
Broadcast机制简要介绍 来源: http://blog.csdn.net/luoshengyang/article/details/6730748 导语 广播机制在Android系统中,也不算 ...
- Codeforces Round #316 (Div. 2) A 水
A. Elections time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
- pat甲级 团体天梯赛 L2-022. 重排链表
L2-022. 重排链表 时间限制 500 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定一个单链表 L1→L2→...→Ln-1→Ln,请 ...
- pat 甲级 Public Bike Management
Public Bike Management (30) 题目描述 There is a public bike service in Hangzhou City which provides grea ...
- Feeling kind of the sorrow
It's almost a long time, in this place, but sometimes, feelings do vary. When I stepped in front of ...
- 关于mysql编码问题
1 查看MySQL编码 SHOW VARIABLES LIKE 'char%';
- hdu 1848 Fibonacci again and again 组合游戏 SG函数
题目链接 题意 三堆石子,分别为\(m,n,p\)个,两人依次取石子,每次只能在一堆当中取,并且取的个数只能是斐波那契数.最后没石子可取的人为负.问先手会赢还是会输? 思路 直接按定义计算\(SG\) ...
- 【Visual Studio】“rc.exe”已退出,代码为 5 ("rc.exe" exited with code 5.)
[解决方案]找到 rc.exe 所在目录,然后 方法1:添加该目录到 VC++ Directories --> Executable Directories中 方法2:添加到系统变量中的Path ...