跨域实现
浏览器-同源策略说明
Ajax请求:=>协议+域名+端口
- 同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。
- 浏览器规定发起ajax时如果请求’‘协议/域名/端口号’'如果3者有一个与当前的浏览器的地址不相同时,则违反了同源策略的规定.则浏览器不予解析返回值.即便两个不同的域名指向同一个ip地址,也非同源。
- 如果违反了同源策略中的任意一条,则叫做跨域访问.浏览器出于安全性的考虑.不予解析返回值(请求正常的被处理,但是接收不到返回值).
注意
跨域主要是浏览器行为,是客户端行为.服务器端一般没有跨域的说法.
跨域1-JSONP
JSONP跨域原理
- 利用javascrpit中的src属性实现跨域请求.
- 自定义回调函数 function callback(xxxx);
- 将返回值结果进行特殊的格式封装 callback(json);
- 由于利用src属性进行调用 所以只能支持get请求类型.
原理分析
我们知道,在页面上有三种资源是可以与页面本身不同源的。它们是:js脚本,css样式文件,图片,像taobao等大型网站,很定会将这些静态资源放入cdn中,然后在页面上连接,如下所示,所以它们是可以链接访问到不同源的资源的。
1)< script type=“text/javascript” src=“某个cdn地址” >< /script>
2)< link type=“text/css” rel=“stylesheet” href=“某个cdn地址” />
3)< img src=“某个cdn地址” alt=“”/>
而jsonp就是利用了< script>标签可以链接到不同源的js脚本,来到达跨域目的。当链接的资源到达浏览器时,浏览器会根据他们的类型来采取不同的处理方式,比如,如果是css文件,则会进行对页面 repaint,如果是img 则会将图片渲染出来,如果是script 脚本,则会进行执行,比如我们在页面引入了jquery库,为什么就可以使用 $ 了呢?就是因为 jquery 库被浏览器执行之后,会给全局对象window增加一个属性: $ ,所以我们才能使用 $ 来进行各种处理。(另外为什么要一般要加css放在头部,而js脚本放在body尾部呢,就是为了减少repaint的次数,另外因为js引擎是单线程执行,如果将js脚本放在头部,那么在js引擎在执行js代码时,会造成页面暂停。)
利用 页面上 script 标签可以跨域,并且其 src 指定的js脚本到达浏览器会执行的特性,我们可以进行跨域取得数据
案例
http://manage.jt.com/test.json 页面封装返回值:
jt.com\testJS.html页面js编辑
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试JSON跨域问题</title>
<script type="text/javascript">
/*JS是解释执行的语言 */
/*定义回调函数 */
function hello(data){
alert(data.name);
}
</script>
<!--该json一直保存到浏览器中等待调用,但是没有函数名称无法调用 -->
<script type="text/javascript" src="http://manage.jt.com/test.json"></script>
<script type="text/javascript" src="http://manage.jt.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
</head>
<body>
<h1>JS跨域问题</h1>
</body>
</html>
访问页面 jt.com\testJS.html
JSONP概念
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的 < script> 元素是一个例外。利用 < script > 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。
JSONP优化策略
1.利用script中的src属性发起请求不方便.不便于程序使用. 能否封装为ajax调用方式
2.在请求路径中拼接一个参数一般的key都是约定俗称的 http:xxx/xx?callback=“自定义函数名称”
3.动态的获取callback的参数名称之后进行特殊的格式封装 callback(JSON);
JSONP的Ajax调用
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSONP测试</title>
<script type="text/javascript" src="http://manage.jt.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
alert("测试访问开始!!!!!")
$.ajax({
url:"http://manage.jt.com/web/testJSONP",
type:"get", //jsonp只能支持get请求
dataType:"jsonp", //dataType表示返回值类型
//jsonp: "callback", //指定参数名称
//jsonpCallback: "hello", //指定回调函数名称
success:function (data){ //data经过jQuery封装返回就是json串
console.log(data);
}
});
})
</script>
</head>
<body>
<h1>JSON跨域请求测试</h1>
</body>
</html>
编辑后端Controller
@RestController
public class JSONPController {
/**
* 实现JSONP跨域请求
* url地址: http://manage.jt.com/web/testJSONP?callback=xxxxxx
* 参数: 暂时没有可以不接
* 返回值: callback(JSON);
*/
@RequestMapping("/web/testJSONP")
public String testJSONP(String callback){
ItemDesc itemDesc = new ItemDesc();
itemDesc.setItemId(1000L).setItemDesc("JSONP测试!!!");
String json = ObjectMapperUtil.toJSON(itemDesc);
return callback+"("+json+")";
}
}
控制台输出
JSONPObject说明
@RequestMapping("/web/testJSONP")
public JSONPObject testJSONP(String callback){
ItemDesc itemDesc = new ItemDesc();
itemDesc.setItemId(1000L).setItemDesc("JSONP测试!!!");
return new JSONPObject(callback, itemDesc);
}
关于ajax请求时间毫秒数的说明
说明:由于浏览器内部有缓存机制,所以如果遇到了一个相同的请求地址,浏览器可能会使用之间的结果.(使用缓存),但是有些数据必须要求浏览器重数据库中动态获取数据,为了避免浏览器缓存一般在url最后添加随机数或者时间毫秒数区分url请求.实现该功能.
跨域2-cors调用
普通跨域访问测试
<script type="text/javascript">
/*$(){}结构必然是jQuery函数类库导入后才能正确执行*/
$(function(){
alert("我执行了AJAX");
//利用jQuery发起AJAX请求
$.get("http://manage.jt.com/test.json",function(data){
alert(data.name);
})
})
</script>
CORS跨域说明
说明:当下的主流的浏览器默认支持cors跨域的形式,但是需要服务器添加响应的信息.否则浏览器不支持数据的获取
实现cors调用
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;
@Configuration //标识我是一个配置类
public class CorsConfig implements WebMvcConfigurer {
//在后端 配置cors允许访问的策略
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("GET","POST") //定义允许跨域的请求类型
.allowedOrigins("*") //任意网址都可以访问
.allowCredentials(true) //是否允许携带cookie
.maxAge(1800); //设定请求长链接超时时间.
}
}
cors调用响应头解析
关于jsonp ,cors跨域的小结
- jsonp本质利用javaScript中的src属性的get请求实现的跨域.
返回值必须经过特殊的格式封装. - cors添加在响应头中信息.指定哪些服务器允许访问.