JavaScript(9)--- 跨域
JavaScript(9)--- 跨域
一、跨域原理(同源策略)
在项目搭建的初期,因为现在项目基本上都是前后端分离,所以不可避免地会遇到跨域问题,而造成跨域的罪魁祸首就是浏览器的同源策略。所以要解决跨域,
我们必须知道什么是浏览器的同源策略。
1、什么是同源策略
概念
它是一个著名的安全策略。所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同
。
当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。不同域之间相互请求资源,就算作“跨域”。
注意
跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。
2、同源策略限制什么
概念
同源策略限制 从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。它的存在可以保护
用户隐私信息,防止身份伪造等(读取Cookie)。
同源策略限制内容有
1、Cookie、LocalStorage、IndexedDB 等存储性内容
2、DOM 节点
3、AJAX 请求不能发送
但是有三个标签是允许跨域加载资源
1.<script src=xxx>
2.<img src=xxx>
3.<link href=xxx>
也就是说这三个标签可以不受同源策略限制,这也是为什么使用<img>
标签的时候,可以引用外部的服务器图片。
解决跨域的方式很多,这里介绍两种最简单的方式:JSONP 和 CORS。
二、JSONP
原理:
<script>是可以跨域的,通过动态创建script标签,然后利用src属性进行跨域。
1、JavaScript示例
前端代码
<html lang="en">
<head>
<title>jsoup</title>
<script type="text/javascript" src="/jquery/jquery-2.1.3.min.js"></script>
<script>
// 1.定义方法 这个是会被回调的函数
function coming(data) {
console.log(data);
}
</script>
<script>
// 2.动态拼接<script>标签,把需要调用的本地方法名传递给后端
let url = "http://localhost:8088/getUser/1?callback=coming";
// 平时都是手写<script src="">,现在我们在代码中动态构造script标签并设置src属性
let script = document.createElement('script');
script.type = "text/javascript";
script.src = url;
// 把script标签加入head(因为script标签本来也是在html的head中),并发起请求,后端响应后浏览器会自动执行返回的script片段
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>
</html>
后段代码
@RestController
public class UserController {
@GetMapping(value = "/getUser/{id}")
public String getUser(@PathVariable("id") String id, String callback) {
// 拼接方法名 + 参数(这就会调用上面script中的coming方法)
return callback + "({\"username\": \"小小\",\"age\": 4 "})";
}
}
2、jquery示例
上面说过了,JSONP其实算是一种对同源策略规则的投机取巧,实现方式可以多种多样。JQuery对JSONP也有实现
<html lang="en">
<head>
<title>jquery示例</title>
<script type="text/javascript" src="/jquery/jquery-2.1.3.min.js"></script>
</head>
<body>
<input type="text" id="result">
<input type="button" onclick="onClick()" value="点击">
</body>
<script>
/**
* 照常使用ajax,只要把dataType改为"jsonp"即可。
* JQuery在前端替我们做了两件事:
* 1.URL后拼接方法名(随机生成)
* 2.解析从后端得到的js片段,把正确的值传入success:function()
*
* 后端还是要按原来的做 JQuery自动帮我们在URL里加了callback参数。
*/
function onClick() {
$.ajax({
type: "GET",
url: "http://localhost:8088/getUser/1",
dataType: "jsonp",
success: function(data){
$('#result').val(data.name);
}
});
}
</script>
</html>
总结
1、JSONP都是GET和异步请求的,不存在其他的请求方式和同步请求,且jQuery默认就会给JSONP的请求清除缓存。
2、JSONP优点是 兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是 仅支持get方法具有局限性。
三、CORS
1、CORS原理
浏览器认为只要后端没返回CORS头(Access-Control-Allow-Origin),就认为后端不允许跨域,返回的数据不可靠。所以只要后端能够返回浏览器需要的请求头,
即可跨域(响应数据就不会被同源策略抛弃),这个是表层原理。
不过目前不是所有浏览器都支持该功能(会自动带上请求头),IE浏览器不能低于IE10。所以最终来看,CORS这种方案不需要前端做任何事情,只需后端配合即可
。
2、示例
前端代码
<html lang="en">
<head>
<script type="text/javascript" src="/jquery/jquery-2.1.3.min.js"></script>
</head>
<body>
<input type="text" id="result">
<input type="button" onclick="onButtonClick()" value="get_button">
</body>
<script>
/**
* 普通AJAX,没有设置jsonp
*/
function onButtonClick() {
$.ajax({
type: "GET",
url: "http://localhost:8080/getUser/1",
success: function(data){
$('#result').val(data.name);
}
});
}
</script>
</html>
后段代码
方式一 方法上加@CrossOrigin
@RestController
public class UserController {
/**
* 在跨域方法上加@CrossOrigin即可完美解决跨域问题
*/
@CrossOrigin("http://localhost:8088")
@GetMapping(value = "/getUser/{id}")
public User getUser(@PathVariable("id") String id) {
User user = new User();
user.setName("小小");
user.setAge(4);
return user;
}
}
方式二 Controller上加@CrossOrigin
@CrossOrigin还可以加载Controller上,这样Controller的所有方法都支持跨域。
@RestController
@CrossOrigin("http://localhost:8088")
public class UserController {
@GetMapping(value = "/getUser/{id}")
public User getUser(@PathVariable("id") String id) {
User user = new User();
user.setName("小小");
user.setAge(4);
return user;
}
}
方式三 @Bean配置跨域Filter
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
//1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//1) 允许的域,如果写*,那么cookie就无法使用了
config.addAllowedOrigin("http://localhost:8088");
//2) 是否发送Cookie信息
config.setAllowCredentials(true);
//3) 允许的请求方式
config.addAllowedMethod("*");
// 4)允许的头信息
config.addAllowedHeader("*");
// 5) 有效时长
config.setMaxAge(3600L);
//2.添加映射路径,我们拦截一切请求
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
//3.返回新的CorsFilter.
return new CorsFilter(configSource);
}
}
总结
本人在实际开发中都是通过CORS解决跨域问题,而且是通过第三种方式配置全局的bean对象。
参考
1、同源策略与跨域
```
别人骂我胖,我会生气,因为我心里承认了我胖。别人说我矮,我就会觉得好笑,因为我心里知道我不可能矮。这就是我们为什么会对别人的攻击生气。
攻我盾者,乃我内心之矛(7)。
```
JavaScript(9)--- 跨域的更多相关文章
- ajax 跨域 headers JavaScript ajax 跨域请求 +设置headers 实践
解决跨域调用服务并设置headers 主要的解决方法需要通过服务器端设置响应头.正确响应options请求,正确设置 JavaScript端需要设置的headers信息 方能实现. 此处手札 供后人参 ...
- 原生JavaScript实现跨域
为什么需要跨域呢?这是因为我们一般的请求都是使用xhr的,但是它只能调用同一个域里面的接口,有时候,我们想要在自己的站点中调用其他站点的接口,这时候就要用到跨域了.其实,跨域并不难,我们可以通过Jav ...
- 【转】ajax 跨域 headers JavaScript ajax 跨域请求 +设置headers 实践
解决跨域调用服务并设置headers 主要的解决方法需要通过服务器端设置响应头.正确响应options请求,正确设置 JavaScript端需要设置的headers信息 方能实现. 此处手札 供后人参 ...
- javascript:cors跨域postMessage、xhr2和xmldomain
一.h5 postMessage node http-server配置服务器 有关配置:请参考我的http://www.cnblogs.com/leee/p/5502727.html 我把文件夹a配置 ...
- arcgis api for JavaScript _跨域请求
arcgis api for JavaScript 中出现跨域请求是常见问题, 通常出现类似如下错误消息类似: XMLHttpRequest cannot load http://10.32.2.7 ...
- 深入浅出JavaScript之跨域总结
什么是跨域 1.document.domain+iframe的设置 2.动态创建script 3.利用iframe和location.hash 4.window.name实现的跨域数据传输 5.使用H ...
- javascript fetch 跨域请求时 session失效问题
javascript 使用fetch进行跨域请求时默认是不带cookie的,所以会造成 session失效. fetch(url, { method: 'POST', credentials: 'in ...
- 前端JavaScript实现跨域的方式(转)
这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...
- JavaScript frame跨域获取元素、修改元素属性、调用其他frame页面方法
今天做了一个frameset的集合页面,其中有多个iframe页面,其中点击frame=leftMenu里的按钮元素后,需要修改frame=Header页面里的一个div元素属性. 1.主页面架构 & ...
随机推荐
- C++走向远洋——26(项目二,2,构造函数与析构函数)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:game.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- Linux - 修改系统的max open files、max user processes(附ulimit的使用方法)【转载】
Linux - 修改系统的max open files.max user processes(附ulimit的使用方法)目录 1 问题说明2 修改max open files3 修改max user ...
- 使用Properties配置文件进行配置读取
#使用Properties配置文件进行配置读取: 例如:有一个配置文件的内容如下: # setting.properties last_open_file=/data/hello.txt auto_s ...
- go语言指南之映射练习
练习:映射 实现 WordCount.它应当返回一个映射,其中包含字符串 s 中每个“单词”的个数.函数 wc.Test 会对此函数执行一系列测试用例,并输出成功还是失败. 你会发现 strings. ...
- C#开发BIMFACE系列36 服务端API之:回调机制
系列目录 [已更新最新开发文章,点击查看详细] 在<C# 开发 BIMFACE 系列文章>中介绍了模型转换.模型对比接口.这2个功能接口比较特殊,发起请求后,逻辑处理是在BIMFA ...
- 使用QT绘制一个多边形
目录 1. 概述 2. 实现 2.1. 代码 2.2. 解析 3. 结果 1. 概述 可以通过QT的重绘事件和鼠标事件来绘制多边形,最简单的办法就是在继承QWidget的窗体中重写paintEvent ...
- 使用Blazor Server 线路处理程序 (circuit handler)跟踪打开的SignalR连接
Blazor服务器允许定义线路处理程序(circuit handler)代码,该处理程序(handler)允许在更改用户线路状态时运行此代码. 线路处理程序(circuit handler)是通过从C ...
- ubuntu16.04设置开机自启服务
网上说了开机自启有许多种方法: 1.最简单的是:在/etc/rc.local的exit 0前面加上你启动服务的脚本文件路径 注:这个脚本文件应写绝对路径! 2.网上:修改rc.local开头的#/bi ...
- RestTemplate 负载均衡原理
RestTemplate 是通过拦截器改变请求的URI的方式来指定服务器的,此处将通过一个自定义LoadBalanced的方式来进行说明 1.导入jar包 <parent> <gro ...
- php不用第三个变量,交换两个数的值
//字符串版本 结合使用substr,strlen两个方法实现 $a="a"; $b="b"; echo '交换前 $a:'.$a.',$b:'.$b.'< ...