
①、什么是跨域我们在开发过程中经常会遇到前后端分离而导致的跨域问题,导致无法获取返回结果。跨域就像分离前端和后端的一道鸿沟,君在这边,她在那边,两两不能往来。
②、什么情况会跨域跨域(CORS)是指不同域名之间相互访问。指的是浏览器不能执行其他网站的脚本,它是由浏览器的同源策略所造成的,是浏览器对于Javascript所定义的安全限制策略。
③、为什么要设计同源策略以上三个条件中有一个条件不同就会产生跨域问题。
二、解决方案 ①、准备工作再举个例子,现在我扮演坏人,我通过一个iframe 加载某宝的登录页面,等傻傻的用户登录我的网站的时候,我就把这个页面弹出,用户一看,阿里唉大公司肯定安全,就屁颠屁颠的输入了密码注意如果没有同源策略,我这个恶意网站就能通过dom操作获取到用户输入的值,从而控制该账户所以同源策略是绝对必要的。
准备两个SpringBoot Module
在CrossDomainA中新增一个HTML页面,用于访问CrossDomainB下的user请求
Tile
在CrossDomainB中新增一个User实体类和UserController控制器
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String userName;
private String password;
}
@RestController
public class UserController {
@RequestMapping("/user")
public User getUser(HttpServletResponse response) {
return new User("彭焕智", "666");
}
}
其中CrossDomainB监听8081端口,CrossDomainA监听8080端口,启动项目,访问8081,正常访问
②、添加响应头解决跨域通过CrossDomainA去访问CrossDomainB呢
IE10以下不支持
response新增一个header
@RestController
public class UserController {
@RequestMapping("/user")
public User getUser(HttpServletResponse response) {
//Access-Control-Allow-Origin允许跨域,*表示允许所有人都允许跨域,也可以指定主机
response.setHeader("Access-Control-Allow-Origin","http://localhost:8080");
return new User("彭焕智", "666");
}
}
实际上CrossDomainA去访问CrossDomainB的时候发送的是两个请求,第一个是option类型的域检请求,询问CrossDomainB服务器是否支持跨域,如果支持,再发送一个get请求给userController,否则第二个请求就不发了
response.setHeader("Access-Control-Allow-Origin","http://localhost:8080");
response.setHeader("Access-Control-Max-Age","10");
除了可以控制跨域请求和域检请求间隔时长,还可以设置允许的请求方法,携带的headers等等
Access-Control-Allow-Method Access-Control-Allow-Headers ...
对于SpringBoot中,直接就提供了支持跨域的注解@CrossOrigin
@RestController
public class UserController {
@RequestMapping("/user")
@CrossOrigin(origins = {"*"}, maxAge = 3600, methods = {RequestMethod.GET, RequestMethod.POST})
public User getUser(HttpServletResponse response) {
return new User("彭焕智", "666");
}
}
③、手写Java反向代理
原理就是,我们通过CrossDomainA去访问CrossDomainB的时候,让CrossDomainA生成一个我们用户自己的一个代理,通过这个代理再去访问CrossDomainB,就好比我们自己去访问CrossDomainB一样,相当于是服务器和服务器之间去请求了,不再是通过浏览器访问,代理收到响应后,再把响应返回给用户
package com.phz.cross_domain.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
@RestController
public class ProxyController {
@Value("${proxy.address}")
//proxy.address=http://127.0.0.1:8081
private String proxyAddress;
@Resource
private RestTemplate restTemplate;
@RequestMapping("/api
@RestController
public class UserController {
@RequestMapping("/api/user")
@CrossOrigin(origins = {"*"}, maxAge = 3600, methods = {RequestMethod.GET, RequestMethod.POST})
public User getUser(HttpServletResponse response) {
return new User("彭焕智", "666");
}
@RequestMapping("/cross")
public String cross() {
return "cross('hello')";
}
}
三、SpringBoot处理跨域问题
不难,注入一个WebMvcConfigure的实现类,重写一个addCorsMappings方法即可,具体配置理解不难
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT","OPTIONS")
.maxAge(3600);
}
}