同源策略,它是由Netscape提出的一个著名的安全策略。
现在所有支持JavaScript 的浏览器都会使用这个策略。
所谓同源是指,域名,协议,端口相同。
当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面
当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,
即检查是否同源,只有和百度同源的脚本才会被执行。 [1]
如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。
我们来模拟下
创建两个项目,一个8080端口的项目,一个8091端口的项目,在8080端口的项目中我们定义一个页面
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<script src="jquery-2.1.1.min.js">script>
<body>
<div id="message">div>
<input type="button" value="get" onclick="getData()">
<input type="button" value="post" onclick="getData2()">
<script>
function getData() {
$.get("http://localhost:8091/hello",function (msg) {
$("#message").html(msg);
})
}
function getData2() {
$.post("http://localhost:8091/hello",function (msg) {
$("#message").html(msg);
})
}
script>
body>
html>
我们在8091端口的项目中定义一个controller
package com.zhouym.cors1;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 〈〉
*
* @author zhouym
* @create 2019/8/9
* @since 1.0.0
*/
@RestController
public class HelloController {
@GetMapping("/hello")
public String query(){
return "get-hello";
}
@PostMapping("/hello")
public String query1(){
return "post-hello";
}
}
都运行启动类,然后页面发起请求
在控制台中就出现了拒绝我们访问的异常信息,那怎么解决呢,就需要用到CORS(跨域源资源共享)(CORS,Cross-origin resource sharing)了,它是一个W3C的标准,它是一份浏览器技术的规范,提供了Web服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略,这是JSONP模式的现代版。
在Spring框架中,对于CORS也提供了相应的解决方案,下面我们就来看看SpringBoot中如何实现CORS。
创建两个项目,端口还是8080和8091的,项目cors1对应8091,项目cors2对应8080,我们在cors2项目中的resources目录下的static下创建一个页面,页面内容为
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<script src="jquery-2.1.1.min.js">script>
<body>
<div id="message">div>
<input type="button" value="get" onclick="getData()">
<input type="button" value="post" onclick="getData2()">
<script>
function getData() {
$.get("http://localhost:8091/hello",function (msg) {
$("#message").html(msg);
})
}
function getData2() {
$.post("http://localhost:8091/hello",function (msg) {
$("#message").html(msg);
})
}
script>
body>
html>
接着我们在cors1项目中创建一个controller
package com.zhouym.cors1;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 〈〉
*
* @author zhouym
* @create 2019/8/9
* @since 1.0.0
*/
@RestController
public class HelloController {
@CrossOrigin(value = "http://localhsot:8080")
@GetMapping("/hello")
public String query(){
return "get-hello";
}
@CrossOrigin(value = "http://localhost:8080")
@PostMapping("/hello")
public String query1(){
return "post-hello";
}
}
通过@CrossOrigin注解配置某一个方法接受某一个域的请求,这个注解表示这两个接口接受来自http://localhost:8080地址的请求,但是这种有个缺陷就是,每个方法上面都需要加上一个注解,显得太过于麻烦了,我们可以创建一个配置类,
实现WebMvcConfigurer 接口,重写里面的addCorsMappings方法,添加可以接受某个域的请求等信息
package com.zhouym.cors1;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 〈〉
*
* @author zhouym
* @create 2019/8/9
* @since 1.0.0
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8080")
.allowedMethods("*")
.allowedHeaders("*");
}
}
/**表示本应用的所有方法都会去处理跨域请求,allowedMethods表示允许通过的请求数,allowedHeaders则表示允许的请求头。