1.什么是跨域
出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的。javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)。
协议,主机(ip),端口号,这三个有一个不同就属于跨域访问
跨域访问前端和后端不设置一些东西的话,不能访问
当前页面URL | 被请求页面URL | 是否跨域 | 原因 |
---|---|---|---|
http://www.test.com/ | http://www.test.com/index.html | 否 | 同源(协议、域名、端口) |
http://www.test.com/ | https://www.test.com/index.html | 跨域 | 协议不同 |
http://www.test.com/ | http://www.test1.com/ | 跨域 | 域名不同 |
http://www.test.com:8080/ | http://www.test.com:8081/ | 跨域 | 端口不同 |
2. 跨域问题的解决方案
比较常用的3种
1.Jsonp 最早的解决方案,利用script标签可以跨域的原理实现。
前端解决方案,不知道好不好用,
2. nginx反向代理
思路是:利用nginx反向代理把跨域改为不跨域,支持各种请求方式
缺点:需要在nginx进行额外配置,语义不清晰
3.CORS【重要】
-
规范化的跨域请求解决方案,安全可靠。
优势:
-
在服务端进行控制是否允许跨域,可自定义规则
- 支持各种请求方式
-
缺点:
会产生额外请求
cors是一种机制,这种机制通过在http头部添加字段,
通常情况下,web应用A告诉浏览器,自己有权限访问应用B
CORS的标准定义是:通过设置http头部字段,让客户端有资格跨域访问资源。通过服务器的验证和授权之后,浏览器有责任支持这些http头部字段并且确保能够正确的施加限制。
JSON与CORS的比较
1.JSONP 只能实现 GET 请求,而 CORS 支持所有类型的 HTTP 请求
2.使用 CORS ,开发者可以是使用普通的 XMLHttpRequest 发起请求和获取数据,比起 JSONP 有更好的错误处理
3.虽然绝大多数现代的浏览器都已经支持 CORS,但是 CORS 的兼容性比不上 JSONP,一些比较老的浏览器只支持 JSONP
3.SpringBoot通过CORS实现跨域
3.1 使用注解实现跨域
@CrossOrigin(origins = "*")
@Slf4j
@RestController
public class EmployeeController {}
@RestController
@CrossOrigin(origins = "*")//实行全局跨域
@Slf4j
public class HelloController {@Referenceprivate HelloService helloService;@GetMapping(value = "/hello",name = "测试")public ResponseEntity hello(@RequestParam String name){String hello = helloService.hello(name);return ResponseEntity.ok(hello);}}
@RestController
public class HiController {@Referenceprivate HiService hiService;@GetMapping(value = "/hi")public ResponseEntity hiName(@RequestParam String name){String respHiName = hiService.hiName(name);return ResponseEntity.ok(respHiName);}}
我们可以看到,后端有连个controller HiController中没有添加@CrossOrigin(origins = "*")
跨域访问试试看
前端:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="js/axios-0.18.0.js"></script>
</head>
<body><button id="hello">hello</button><button id="hi">hi</button><script>var hello = document.getElementById("hello");var hi = document.getElementById("hi");hello.onclick = function(){axios.get("http://localhost:8082/hello?name=张三").then(resp=>{alert(resp.data);})}hi.onclick = function(){axios.get("http://localhost:8082/hi?name=张三").then(resp=>{alert(resp.data);})}</script>
</body>
</html>
首先肯定是跨域,点击hi 的话会报错,当hiController中添加@CrossOrigin(origins = "*")
就ok了
2.通过全局配置解决跨域请求
如果说你有好多Controller 每一个都要配置,那么不值当的,所有可以用这种方法
@Configuration
public class DemoWebMvcConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**") // 匹配了所有的URL.allowedHeaders("*") // 允许跨域请求包含任意的头信息.allowedMethods("*") // 设置允许的方法.allowedOrigins("*") // 设置允许跨域请求的域名.allowCredentials(false); // 是否允许证书,默认false}
}