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...
