跨域问题解决方式(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...

时间: 2024-10-27 07:43:37

跨域问题解决方式(HttpClient安全跨域 &amp; jsonp跨域)的相关文章

使用Httpclient来替代客户端的jsonp跨域解决方案

最近接手一个项目,新项目需要调用老项目的接口,但是老项目和新项目不再同一个域名下,所以必须进行跨域调用了,但是老项目又不能进行任何修改,所以jsonp也无法解决了,于是想到了使用了Httpclient来进行服务端的“跨域”来替代jsonp的客户端跨域方案. 上一篇博文中,详细剖析了jsonp的跨域原理,本文使用Httpclient来替代jsonp的客户端跨域方案. 先去 http://hc.apache.org/downloads.cgi 下载最新版httpclient.解压tutorial文件

AJAX跨域问题解决方法(1)——禁止浏览器进行跨域限制

思路:通过命令行修改浏览器启动参数,使得浏览器不进行跨域检查,从而允许跨域 方法:命令行参数启动浏览器后添加参数--disable-web-security 例:chrome --disable-web-security --disabl-web-security参数的作用是禁止浏览器进行跨域检查 但是,这种方法有三个缺点: 1.每次启动浏览器都需要通过命令行启动,太过繁琐 2.该方法会导致安全性方面的问题 3.该方法是客户端方面的改动,在实际使用中,在每个客户端上都禁止浏览器进行跨域检查不太现

前端前后端分离开发调试过程中跨域问题解决方式

1. 将后台代码部署到你的电脑(安装各种jdk或者环境软件) - 麻烦! 后台改了代码得找后台要 2. 将前端代码放到跟服务器代码一起 - 麻烦! 前端改一下东西就得上传一次 3. 使用方便快捷的nginx做代理 (仅仅需要下载nginx稍加配置 , 一次性避免上面两点缺点) 详情(有道云笔记个人记录总结): http://note.youdao.com/noteshare?id=97d0047e7a87d7809d2b15e6be04eec1

JS的jsonp是什么?5分钟学会jsonp跨域请求

一.jsonp是什么? jsonp是解决跨域请求的一种技术.浏览器为了防止CSRF攻击会采用同源策略(协议/主机/端口均相同)限制,对非同源发起http请求(即跨域请求)会被浏览器阻止. 二.jsonp跨域请求的原理? script标签的src属性不受同源策略限制,用此方式对非同源服务器请求资源,返回的JS代码会调用指定的函数,携带的参数就是所需的数据,这样就完成了跨域请求. 三.原生JS的jsonp跨域请求: 首先声明一个处理返回数据的函数,返回的JS代码会调用此函数: function do

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

1 错误场景 今天要把项目部署到外网的时候,出现了这样的问题, 我把两个项目放到自己本机的tomcat下, 进行代码调试, 运行 都没有问题的, 一旦把我需要调用接口的项目B放到其他的服务器上, 就会报错, 无法通过Ajax调用springMVC的接口, 这是什么原因呢? 当我使用json ajax post请求传递数据的时候在web端出错:XMLHttpRequest cannot loadhttp://ip:8082/security/auth/outside.do. Origin http

web项目中的跨域问题解决方法

一种是JSONP 一种是 CORS. 在客户端Javascript调用服务端接口的时候,如果需要支持跨域的话,需要服务端支持. JSONP的方式就是服务端对返回的值进行回调函数包装,他的优点是支持众多的浏览器, 缺点是仅支持Get的方式对服务端请求. 另一种主流的跨域方案是CORS,他仅需要服务端在返回数据的时候在相应头中加入标识信息.这种方式非常简便.唯一的缺点是需要浏览器的支持,一些较老的浏览器可能不支持CORS特性. 跨域支持是创建WebService时应该考虑的一个功能点,文中是使用Se

关于跨域处理方式

什么是跨域: 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被当作是不同的域. 一.通过jsonp跨域 首先在客户端注册一个callback (如:'jsoncallback'), 然后把callback的名字(如:jsonp1236827957501)传给服务器.注意:服务端得到callback的数值后,要用jsonp1236827957501

IE8 jquery跨域问题解决

1.IE8 jquery跨域问题解决: 加下面code 源地址: https://github.com/dkastner/jquery.iecors/blob/master/jquery.iecors.js (function( jQuery ) { // Create the request object // (This is still attached to ajaxSettings for backward compatibility) jQuery.ajaxSettings.xdr

深入浅出:了解jsonp跨域的九种方式

什么是“”跨域”: 跨域访问,简单来说就是 A 网站的 javascript 代码试图访问 B 网站,包括提交内容和获取内容.由于安全原因,跨域访问是被各大浏览器所默认禁止的.当一个域与其他域建立了信任关系后,2个域之间不但可以按需要相互进行管理,还可以跨网分配文件和打印机等设备资源,使不同的域之间实现网络资源的共享与管理.这就形成了“跨域”. 广义的跨域: 1.) 资源跳转: A链接.重定向.表单提交2.) 资源嵌入: <link>.<script>.<img>.&l