Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 442|回复: 0

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

[复制链接]
  • TA的每日心情
    奋斗
    4 天前
  • 签到天数: 802 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726006
    发表于 2021-6-2 12:48:30 | 显示全部楼层 |阅读模式

     

    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.substring(0, arr.lastIndexOf("="));
    				String value = arr.substring(arr.lastIndexOf("=") + 1);
    				data = 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...

     

     

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-11-15 10:16 , Processed in 2.128563 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表