跨域和跨域方式(浏览器)

2 篇文章 0 订阅
1 篇文章 0 订阅

什么是跨域?
理解跨域首先必须要了解同源策略。
同源策略:是浏览器上为安全性考虑实施的非常重要的安全策略。
何谓同源: URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则表示他们同源。
例如:

http://www.example.com与以下比较:
http://api.example.com/detail.html  不同源 域名不同  
https//www.example.com/detail.html   不同源 协议不同  
http://www.example.com:8080/detail.html    不同源    端口不同  
http://api.example.com:8080/detail.html    不同源    域名、端口不同  
https://api.example.com/detail.html    不同源    协议、域名不同  
https://www.example.com:8080/detail.html    不同源    端口、协议不同  
http://www.example.com/detail/index.html    同源    只是目录不同

同源策略解析:
(1)浏览器的同源策略,限制了来自不同源的"document"或脚本,对当前"document"读取或设置某些属性。 从一个域上加载的脚本不允许访问另外一个域的文档属性。
举个例子:
比如一个恶意网站的页面通过iframe嵌入了银行的登录页面(二者不同源),如果没有同源限制,恶意网页上的javascript脚本就可以在用户登录银行的时候获取用户名和密码。
(2)同源策略是浏览器在接收加载资源之前对其来源进行了检查,然后限制加载;
(3)同源策略使浏览器允许跨域写,而不允许跨域读,写就是上行,发送请求,读就是下行,接受响应;
(4)在浏览器中,<script>、<img>、<iframe>、<link>等标签都可以加载跨域资源,而不受同源限制,但浏览器限制了JavaScript的权限使其不能读、写加载的内容。

跨域是指从一个域名的网页去请求另一个域名的资源。比如从www.baidu.com 页面去请求 www.google.com 的资源。跨域的严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域,并有以下注意事项:

1、表单默认提交(跳转页面或刷新页面)、超链接访问域外的资源,这是允许的,因为在点击按钮/超链接时,浏览器地址已经变了,这就是一个普通的请求,不属于跨域;

2、ajax(借助xmlhttprequest)跨域请求,这是被禁止的,因为ajax就是为了接受接受响应,这违背了,不允许跨域读的原则;

3、jsonp属于跨域读且形式限制为GET方式,它利用了script标签的特性;这是允许的。因为浏览器把跨域读脚本,当作例外,类似的img、iframe的src都可以请求域外资源;

4、出现Access control allow origin错误,说明是跨域请求失败!浏览器发送请求成功,同时浏览器也接收到响应了,但是限制了XmlHttpRquest接收请求,不会让xmlhttprequest接受到响应,并且在js控制台报错。这也就是我们在网络控制台(Network)能看见http 状态码是200,但是在js控制台(Console)出现js错误的原因。

为什么浏览器要限制跨域访问呢?

原因就是安全问题:如果一个网页可以随意地访问另外一个网站的资源,那么就有可能在客户完全不知情的情况下出现安全问题。
比如下面的操作就有安全问题:
用户访问www.mybank.com ,登陆并进行网银操作,这时cookie啥的都生成并存放在浏览器
用户突然想起件事,并迷迷糊糊地访问了一个邪恶的网站 www.xiee.com
这时该网站就可以在它的页面中,拿到银行的cookie,比如用户名,登陆token等,然后发起对www.mybank.com 的操作。

如果这时浏览器不予限制,并且银行也没有做响应的安全处理的话,那么用户的信息有可能就这么泄露了。

既然有安全问题,那为什么又要跨域呢?

 有时公司内部有多个不同的子域,比如一个是location.company.com ,而应用是放在app.company.com, 
 这时想从 app.company.com去访问 location.company.com 的资源就属于跨域。

跨域访问的几种方式

  1. 通过jsonp方式进行跨域(仅限get请求):
    (1)前端jquery的jsonp方式;
    (2)前端AngularJS的jsonp方式;
    (3)手动实现jsonp;
  2. 服务器端设置请求头Access-Control-Allow-Origin实现跨域;

1、通过jsonp方式进行跨域(仅限get请求);
jsonp原理:

其本质是利用了标签具有可跨域的特性,由服务端返回预先定义好的javascript函数的调用,并且将服务端数据以该函数参数的形式传递过来。

JSONP技术实际和Ajax没有关系。
我们知道<script>标签可以加载跨域的javascript脚本,并且被加载的脚本和当前文档属于同一个域。
因此在文档中可以调用/访问脚本中的数据和函数。
如果javascript脚本中的数据是动态生成的,那么只要在文档中动态创建<script>标签就可以实现和服务端的数据交互。
JSONP就是利用<script>标签的跨域能力实现跨域数据的访问,请求动态生成的JavaScript脚本同时带一个callback函数名作为参数。
其中callback函数本地文档的JavaScript函数,服务器端动态生成的脚本会产生数据,并在代码中以产生的数据为参数调用callback函数。当这段脚本加载到本地文档时,callback函数就被调用。

代码如下:

(1)前端jquery的jsonp方式:

///跨域ajax请求,jsonp,页面地址http://127.0.0.1:8020/jsonp/index.html
	function crossDomainJsonp() {
		$.ajax({
			type:"get", 
			url:"http://192.168.2.23/pdf/crossDomainJsonp1.do",
			async:true,
			data:{},
			dataType: "jsonp",	//返回类型为jsonp,实现跨域
			jsonp:"callback",	//jsonp和jsonpCallBack相当于在url后添加一个参数:?callback=back
			jsonpCallback:"back",	//设定回调函数的名字,传到后台,进行包装,不设定自动生成
			success: function(data) {	//成功执行处理,对应后台返回的back(data)方法
				alert(data);
				console.log(data);
			}
		});
	}

后台

/**
	 * 
	* @Title: crossDomainJsonp1
	* @Description: TODO(jsonp方式一)
	* @return MappingJacksonValue    返回类型
	* @param callback
	* @return
	 */
	@RequestMapping(value="crossDomainJsonp1", method=RequestMethod.GET)
	@ResponseBody
	public MappingJacksonValue crossDomainJsonp1(String callback) {
		Map<String, Object> resultMap = new HashMap<>();
		try {
			resultMap.put("success", true);
		} catch (IllegalStateException e) {
			e.printStackTrace();
			resultMap.put("success", false);
		}
		//包装jsonp
		MappingJacksonValue jacksonValue = new MappingJacksonValue(resultMap);
		//设置包装的回调方法名
		jacksonValue.setJsonpFunction(callback);

		return jacksonValue;
	}
	
	
	/**
	 * 
	* @Title: crossDomainJsonp2
	* @Description: TODO(jsonp方式二)
	* @return String    返回类型
	* @param callback
	* @return
	 */
	@RequestMapping(value="crossDomainJsonp2", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE + ";charset=utf-8")
	@ResponseBody
	public String crossDomainJsonp2(String callback) {
		Map<String, Object> resultMap = new HashMap<>();
		try {
			resultMap.put("success", true);
		} catch (IllegalStateException e) {
			e.printStackTrace();
			resultMap.put("success", false);
		}
		//把对象转换成json数据(自定义的JSONUtils)
		String jsonResult = JSONUtils.objectToJson(resultMap);
		//拼接字符串
		String resultStr = callback + "(" + jsonResult + ");";

		return resultStr;
	}

(2)前端AngularJS的jsonp方式:AngularJS的$http 也提供了对jsonp的访问,直接调用jsonp进行跨域访问

$http.jsonp('http://192.168.2.23/pdf/crossDomainJsonp1.do?callback=back')
		.success(function(data) {
			alert(data);
			console.log(data);
		}).error(function(err) {
			alert('error:' + err);
		});

后台同上

(3)手动实现jsonp
jsonp的本质而都是通过加载javascript的方式来做的,所以如果项目没有依赖jQuery或者AngularJS,则可以自己手动实现jsonp的调用。

原理很简单,就是用javascript动态加载一个script文件,同时定义一个callback函数给script执行而已。

	//定义callback 函数
	function back1(data) {
		alert(data);
		console.log(data);
	}
	//通过添加script标签,进而执行js(执行完成应该删除生成的script)
	function crossDomain2() {
		//创建并加载script
		var script = document.createElement('script');
		script.src = 'http://192.168.2.23/pdf/crossDomainJsonp1.do?callback=back1';
		document.body.appendChild(script);
	}

后台同上

2、服务器端设置请求头Access-Control-Allow-Origin实现跨域
参考链接:Access control allow origin 简单请求和复杂请求http://blog.csdn.net/wangjun5159/article/details/49096445

传统的跨域请求没有好的解决方案,无非就是jsonp和iframe,随着跨域请求的应用越来越多,W3C提供了跨域请求的标准方案(Cross-Origin Resource Sharing)。
IE8、Firefox 3.5 及其以后的版本、Chrome浏览器、Safari 4 等已经实现了 Cross-Origin Resource Sharing 规范,实现了跨域请求。
在服务器响应客户端的时候,带上Access-Control-Allow-Origin头信息。
• 如果设置 Access-Control-Allow-Origin:*,则允许所有域名的脚本访问该资源。
• Access-Control-Allow-Origin:http://www.phpddt.com.com,允许特定的域名访问。

前端:正常的ajax请求
后台:

/**
	 * 
	* @Title: crossDomain1
	* @Description: TODO(通过设置响应头Access-Control-Allow-Origin解决跨域请求)
	* @return Map<String,Object>    返回类型
	* @param response
	* @return
	 */
	@RequestMapping(value="crossDomain1", method=RequestMethod.GET)
	@ResponseBody
	public Map<String, Object> crossDomain1(HttpServletResponse response) {
		Map<String, Object> resultMap = new HashMap<>();
		try {
			//利用Access-Control-Allow-Origin响应头解决跨域请求
//			response.setHeader("Access-Control-Allow-Origin", "*");
			response.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8020");
			resultMap.put("success", true);
		} catch (IllegalStateException e) {
			e.printStackTrace();
			resultMap.put("success", false);
		}
		return resultMap;
	}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值