跨域問題解決方式(HttpClient安全跨域 & jsonp跨域)

 

1 錯誤場景                                         java

       今天要把項目部署到外網的時候,出現了這種問題, 我把兩個項目放到本身本機的tomcat下, 進行代碼調試, 執行python

都沒有問題的, 一旦把我需要調用接口的項目B放到其它的server上, 就會報錯, 沒法經過Ajax調用springMVC的接口,c++

這是什麼緣由呢? web

      當我使用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.ajax

 

2 初識jsonp                               spring

      通過在網上查找, 網上大多數說是跨域問題. 解決跨域問題聽說是jsonp, 百度了一篇文章, 不管三七二十一就一下json

子把ajax傳遞的數據類型dataType 改爲爲jsonp, 並使用get方式, 單純的以爲, json和jsonp沒啥差異, 執行, 報錯, 如c#

下圖所看到的:跨域

 

      沒有了上述的 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...

相關文章
相關標籤/搜索