要了解跨域,首先呢先了解下同源策略,然后再AJAX跨域访问被禁止的原因,最后实现跨域的解决方式。
同源策略
同源策略(Same Origin Policy,SOP)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
所谓同源是指【协议+域名+端口】相同。
当一个浏览器的两个tab页中分别打开百度和谷歌的页面时,当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。 如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以google.com下的js脚本采用ajax读取baidu.com里面的文件数据是会报错的。
如何判断是否是同源,可以查看该表
不受同源策略限制的:
•页面中的链接,重定向以及表单提交是不会受到同源策略限制的。
•跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的,,,等
同源策略的限制
1.不能获取不同源的cookie,LocalStorage 和 indexDB
2.不能获取非同源的DOM
3.不能发送非同源的ajax请求。(准确说应该是可以向非同源的服务器发起请求,但是返回的数据会被浏览器拦截)
同源策略由浏览器执行
所有的限制都是因为浏览器的作用,这是因为浏览器为保护用户隐私而才去的措施。
为什么要有同源策略
采用同源策略主要是因为安全。若非同源下的cookie等隐私数据可以被随意获取,非同源下的DOM可以的随意操作,ajax可以任意请求的话,用户的各种隐私势必泄露。
再来细说一下同源策略的限制
1.不能获取不同源的cookie,LocalStorage 和 indexDB
这个东西很好理解,是为了防止恶意网站获取用户其他网站的cookie数据
2.不能让获取非同源的DOM
如果没有这一条,恶意网站可以通过iframe打开银行页面,可以获取dom就相当于可以获取整个银行页面的信息。
3.不能发送非同源的ajax请求。
看个大佬写的小案例
实现跨域的两种方式
1、JSONP
没有使用过,一直也没有听说过,就不写了
2、Cors
Cors(跨域源资源共享)
(Cors,Cross-origin resource sharing)是一个W3C标准它是一份浏览器技术的规范
它提供了Web服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略
这是JSONP模式的现代版
3、开始跨域
首先,我们需要创建两个SpringBoot项目,一个服务提供者(provider),一个服务消费者(consumer),只需要引入以下依赖即可:
<!-- web支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- thymeleaf模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
然后我们修改服务提供者(provider)的application.yml文件,加入配置信息:
#提供服务的端口号
server:
port: 8080
在服务提供者(provider)项目中的resource目录下的templates目录下新建一个html文件:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Cors跨域请求</title>
<script type="text/javascript" th:src="@{/js/jquery-3.2.0.min.js}"></script>
</head>
<body>
<input type="button" onclick="getRequest()" value="GET请求">
<input type="button" onclick="postRequest()" value="POST请求">
<script>
function getRequest() {
$.get('http://localhost:8081/index', function (res) {
$('body').html(res);
})
}
function postRequest() {
$.post('http://localhost:8081/index', function (res) {
$('body').html(res);
})
}
</script>
</body>
</html>
然后我们修改服务消费者(consumer)的application.yml文件,加入配置信息:
#消费服务的端口号
server:
port: 8081
然后新建一个controller,在controller包下面新建一个IndexController文件:
接下来,我们启动这两个项目:访问 http://localhost:8080/,点击页面中的按钮,会出现以下提示错误:
Access to XMLHttpRequest at 'http://localhost:8081' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
这是提醒我们,在http://localhost:8081中访问http://localhost:8080,受到了限制,原因是我们没有开启跨域,我们有两种方法开启跨域(访问http://localhost:8081成功,但是返回的数据会被浏览器拦截)
1、@CrossOrigin()
@CrossOrigin(value = "http://localhost:8080")
@GetMapping("index")
public String gindex() {
return "get hello;";
}
@CrossOrigin(value = "http://localhost:8080")
@PostMapping("index")
public String pindex() {
return "post hello;";
}
在controller请求的方法上加上该注解,即表示该接口开启了跨域,允许http://localhost:8081进行访问
2、Config配置文件
以上加注解在方法上显得很繁杂,我们可以将整个项目配置为开启跨域,在config包下面新建一个CorsConfig文件:
package com.zyxx.cors.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author lizhou
* 跨域配置
* @date 2019/8/16
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// 所有请求都会处理跨域
registry.addMapping("/**")
// 允许谁访问
.allowedOrigins("http://localhost:8081")
// 允许通过的请求数
.allowedMethods("*")
// 允许的请求头
.allowedHeaders("*");
}
}
以上参考网页如下
SpringBoot中使用Cors开启跨域
AJAX跨域访问被禁止的原因
浏览器同源策略和跨域的实现方法