跨域和同源策略问题,JSONP、CORS解决跨域问题

问题案例

在服务器 manage.qiu.com (这里用到了反向代理为服务器设置了域名)的静态文件中加上一个test.html页面和test.json文件
test.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试JSON跨域问题</title>
<script type="text/javascript" src="http://manage.qiu.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript">
	$(function(){
		$.get("http://manage.qiu.com/test.json",function(data){
			alert(data.name);
		})
	})
</script>
</head>
<body>
	<h1>JSON跨域请求测试</h1>
</body>
</html>

test.json:

{"id":"1","name":"tom"}

此时在浏览器输入网址manage.qiu.com/test.html
在这里插入图片描述
成功显示页面和返回json文件中的数据!!!
2.
如果此时我们输入的网址是通过服务器对应的IP和端口来访问test.html
在这里插入图片描述
成功返回页面,却没有得到json文件中的数据!!!
看浏览器控制台报错信息:
在这里插入图片描述
这句话翻译过来就是:已被CORS策略阻止:请求的资源上不存在“Access Control Allow Origin”标头。既表示没有被授权返回数据!
这就是跨域!!!

浏览器的同源策略

同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)。
如果浏览器的地址与Ajax的请求地址 协议名称://域名地址:端口号 如果都相同则满足同源策略.浏览器可以正常的解析返回值. 如果三者之间有一个不同,则违反了同源策略.浏览器不会解析返回值.
如果浏览器的地址与Ajax的请求地址 协议名称://域名地址:端口号 如果都相同则满足同源策略.浏览器可以正常的解析返回值. 如果三者之间有一个不同,则违反了同源策略.浏览器不会解析返回值.

何为跨域

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
在这里插入图片描述

跨域时受到限制的资源

  • 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
  • 无法接触非同源网页的 DOM
  • 无法向非同源地址发送 AJAX 请求

跨域解决方法

JSONP跨域访问

通过文章开始的案例我们不难测试到,跨域时受到限制的资源中包括了发送AJAX请求返回的json,但跨域访问的jquery文件包却没有受到限制,即

<script type="text/javascript" src="http://manage.qiu.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>

本行代码所请求的资源得到了成功返回。
这便是jsonp。
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 服务器A 的网页无法与服务器B沟通,而 HTML 的元素是一个例外。利用元素的这个开放策略,网页可以得到从其他来源动态生产的JSON资料,而这种模式就是所谓的JSONP。用JSONP抓到的资料并不是JSON,而是任意的JavaScript,用JavaScript直译器执行而不是用JSON解析器解析。

JSONP原理说明

1.利用javaScript中的src属性可以跨域的访问.

<script type="text/javascript" src="http://manage.qiu.com/test.json"></script>

2.提前准备一个回调函数 callback()

/*定义回调函数  */
		function hello(data){
			alert(data.name);
		}

3.将test.json中的数据结果进行特殊的格式封装. callback(JSON数据)

hello({"id":"1","name":"tom"})

即使用新页面testjs.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试JSON跨域问题</title>
<script type="text/javascript" src="http://manage.qiu.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript">
	function hello(data){
		alert(data.name);
	}
</script>
	<script type="text/javascript" src="http://manage.qiu.com/test.json"></script>
</head>
<body>
	<h1>JSON跨域请求测试</h1>
</body>
</html>

获取成功:
在这里插入图片描述

JSONP高级API的使用

示例:
testjson.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSONP测试</title>
<script type="text/javascript" src="http://manage.qiu.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript">
	$(function(){
		alert("测试访问开始!!!!!")
		$.ajax({
			url:"http://manage.qiu.com/web/testJSONP",
			type:"get",				//jsonp只能支持get请求
			dataType:"jsonp",       //dataType表示返回值类型
			jsonp: "callback",    //指定参数名称
			jsonpCallback: "hello",  //指定回调函数名称
			success:function (data){   //data经过jQuery封装返回就是json串
				alert("获取数据"+data.itemId+data.itemDesc);
			}	
		});	
	})
</script>
</head>
<body>
	<h1>JSON跨域请求测试</h1>
</body>
</html>

编辑后端服务器

import com.fasterxml.jackson.databind.util.JSONPObject;
import com.jt.pojo.ItemDesc;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class JSONController {
    @RequestMapping("/web/testJSONP")
    public JSONPObject testJSONP(String callback){
        ItemDesc itemDesc = new ItemDesc();
        itemDesc.setItemId(1000L).setItemDesc("JSONP远程调用!!!");
        JSONPObject jsonpObject = new JSONPObject(callback, itemDesc);
        return jsonpObject;
    }
}

CORS跨域实现

CORS介绍

因为出于安全的考虑, 浏览器不允许Ajax调用当前源之外的资源. 即浏览器的同源策略.
CORS需要浏览器和服务器同时支持。目前,所有主流浏览器都支持该功能,IE浏览器不能低于IE10。在浏览器端, 整个CORS通信过程都是浏览器自动完成,在请求之中添加响应头信息,如果服务器允许执行跨域访问.,则浏览器的同源策略放行.
在这里插入图片描述
url发送到服务器,服务器允许其跨域,那么浏览器将不再拦截!

跨域检验

在这里插入图片描述
几乎所有的浏览器都兼容CORS的方式,但是由于服务器不允许跨域,所以请求被拒.

配置后端服务器

在项目的配置类中加入CORSConfig配置类

package com.jt.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 完成CORS跨域配置: 实现思路在请求的响应头中添加访问信息.
 */
@Configuration
public class CORSConfig implements WebMvcConfigurer{//web项目的全局配置的接口.

    /**
     * 参数介绍:
     *      1.addMapping()  哪些请求可以进行跨域操作
     *        addMapping("/**")   表示所有访问后端的服务器的请求都允许跨域
     *        addMapping("/addUser/**")  表示部分请求可以跨域
     *        /*       只能拦截一级目录
     *        /**      可以拦截多级目录
     *
     *      2.allowedOrigins("*")  允许哪些网站跨域
     *      3.allowCredentials(true)  请求跨域时是否允许携带Cookie/Session相关
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowCredentials(true);
                //.maxAge();       默认30分钟 是否允许跨域请求 30分钟之内不会再次验证
                //.allowedMethods() 允许请求类型
    }
}

响应信息

在这里插入图片描述
此时显示允许。

跨域问题总结

1.什么叫跨域 浏览器解析Ajax时,发起url请求违反了同源策略时,称之为跨域.
2.什么时候用跨域 一般A服务器需要从B服务器中获取数据时,可以采用跨域的方式.
3.什么是JSONP JSONP是JSON的一种使用模式 利用javaScript中的src属性进行跨域请求.(2.自定义回调函数,3.将返回值进行特殊格式封装)
4.什么是CORS CORS是当前实现跨域的主流方式,现在所有的主流浏览器都支持,需要在服务器端配置是否允许跨域的配置. 只要配置了(在响应头中添加允许跨域的标识),则同源策略不生效,则可以实现跨域.

评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值