![](https://cdn.zimug.com/wx-zimug.png)
## 一、什么是跨域访问
说到跨域访问,必须先解释一个名词:同源策略。所谓同源策略就是在浏览器端出于安全考量,向服务端发起请求必须满足:协议相同、Host(ip)相同、端口相同的条件,否则访问将被禁止,该访问也就被称为跨域访问。
虽然跨域访问被禁止之后,可以在一定程度上提高了应用的安全性,但也为开发带来了一定的麻烦。比如:我们开发一个前后端分离的易用,页面及js部署在一个主机的nginx服务中,后端接口部署在一个tomcat应用容器中,当前端向后端发起请求的时候一定是不符合同源策略的,也就无法访问。那么我们如何解决这个问题?就是本文需要向大家说明的内容。
## 二、跨域访问的解决方案有哪些?
### 2.1.第一类方案:前端解决方案
虽然浏览器对于不符合同源策略的访问是禁止的,但是仍然存在例外的情况,如以下资源引用的标签不受同源策略的限制:
* html的script标签
* html的link标签
* html的img标签
* html的iframe标签:对于使用jsp、freemarker开发的项目,这是实现跨域访问最常见的方法,
除了基于HTML本身的特性实现跨域访问,我们还可以使用jsonp、window的postMessage实现跨域访问。这些都是前端实现跨域访问的方式。
### 2.2.第二类方案:使用代理
实际上对跨域访问的支持在服务端实现起来更加容易,最常用的方法就是通过代理的方式,如:
* nginx或haproxy代理跨域
* nodejs中间件代理跨域
其实实现代理跨域的逻辑非常简单:就是在不同的资源服务:js资源、html资源、css资源、接口数据资源服务的前端搭建一个中间层,所有的浏览器及客户端访问都通过代理转发。所以在浏览器、客户端看来,它们访问的都是同一个ip、同一个端口的资源,从而符合同源策略实现跨域访问。
![](https://img.kancloud.cn/8c/92/8c92445029891a33300b83002015ea88_801x580.png)
### 2.3 第三类方案:CORS
跨域资源共享(CORS):通过修改Http协议header的方式,实现跨域。说的简单点就是,通过设置HTTP的响应头信息,告知浏览器哪些情况在不符合同源策略的条件下也可以跨域访问,浏览器通过解析Http协议中的Header执行具体判断。具体的Header如下:
**CROS跨域常用header**
Access-Control-Allow-Origin: 允许哪些ip或域名可以跨域访问
Access-Control-Max-Age: 表示在多少秒之内不需要重复校验该请求的跨域访问权限
Access-Control-Allow-Methods: 表示允许跨域请求的HTTP方法,如:GET,POST,PUT,DELETE
Access-Control-Allow-Headers: 表示访问请求中允许携带哪些Header信息,如:`Accept`、`Accept-Language`、`Content-Language`、`Content-Type`
## 三、SpringBoot下实现CORS的四种方式
为大家介绍四种实现CORS的方法,两种是全局配置,两种是局部接口生效的配置。一般来说,SpringBoot项目采用其中一种方式实现CORS即可。
### 3.1.使用CorsFilter进行全局跨域配置
```
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//开放哪些ip、端口、域名的访问权限,星号表示开放所有域
config.addAllowedOrigin("*");
//是否允许发送Cookie信息
config.setAllowCredentials(true);
//开放哪些Http方法,允许跨域访问
config.addAllowedMethod("GET","POST", "PUT", "DELETE");
//允许HTTP请求中的携带哪些Header信息
config.addAllowedHeader("*");
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
config.addExposedHeader("*");
//添加映射路径,“/**”表示对所有的路径实行全局跨域访问权限的设置
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
return new CorsFilter(configSource);
}
}
```
### 3.2. 重写WebMvcConfigurer的addCorsMappings方法(全局跨域配置)
```
@Configuration
public class GlobalCorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") //添加映射路径,“/**”表示对所有的路径实行全局跨域访问权限的设置
.allowedOrigins("*") //开放哪些ip、端口、域名的访问权限
.allowCredentials(true) //是否允许发送Cookie信息
.allowedMethods("GET","POST", "PUT", "DELETE") //开放哪些Http方法,允许跨域访问
.allowedHeaders("*") //允许HTTP请求中的携带哪些Header信息
.exposedHeaders("*"); //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
}
};
}
}
```
### 3.3.使用CrossOrigin注解(局部跨域配置)
* 将CrossOrigin注解加在Controller层的方法上,该方法定义的RequestMapping端点将支持跨域访问
* 将CrossOrigin注解加在Controller层的类定义处,整个类所有的方法对应的RequestMapping端点都将支持跨域访问
```
@RequestMapping("/cors")
@ResponseBody
@CrossOrigin(origins = "http://localhost:8080", maxAge = 3600)
public String cors( ){
return "cors";
}
```
### 3.4 使用HttpServletResponse设置响应头(局部跨域配置)
这种方式略显麻烦,不建议在SpringBoot项目中使用。
```
@RequestMapping("/cors")
@ResponseBody
public String cors(HttpServletResponse response){
//使用HttpServletResponse定义HTTP请求头,最原始的方法也是最通用的方法
response.addHeader("Access-Control-Allow-Origin", "http://localhost:8080");
return "cors";
}
```
## 四、实现与测试
在SpringBoot**项目外**随便定义一个HTML,并写代码触发如下的ajax代码。(触发过程我就不写了,定义一个按钮加一个监听函数即可)。以下是跨域AJAX请求验证的核心代码:
```
$.ajax({
url: 'http://localhost:8090/cors',
type: "POST",
xhrFields: {
withCredentials: true //允许发送Cookie信息
},
success: function (data) {
alert("跨域请求配置成功")
},
error: function (data) {
alert("跨域请求配置失败")
}
})
```
* 跨域请求配置成功表示:我们的跨域配置生效,ajax请求可以正确访问服务端接口。
* 跨域请求配置失败表示:我们的跨域配置未生效,请参照检查第三节检查各项配置是否正确。
- 核心内容介绍
- 问题Q&A汇总
- 本文档已达38万字
- 联系作者-代码工具获取
- 作者的其他作品推荐
- vue深入浅出系列
- Spring Security-JWT-OAuth2一本通
- 实战前后端分离RBAC权限管理系统
- 实战SpringCloud微服务从青铜到王者
- 第一章 spring boot 2.x基础及概念入门
- 1.1.spring boot 产生的背景及其优势
- 1.2.helloworld及项目结构介绍
- 1.3.需要先了解的核心概念
- 1.4.提高开发效率必备工具lombok
- 1.5.IDEA环境下的热加载与热部署
- 1.6.开发过程中常用IDEA插件
- 第二章 RESTful接口实现与测试
- 2.1.RESTful接口与http协议状态表述
- 2.2.1.Spring常用注解及基础讲解
- 2.2.2.常用注解开发一个RESTful接口
- 2.2.3.配合前端axios传参总结
- 2.3.1 JSON数据处理与PostMan测试
- 2.3.2. Jackson全局配置
- 2.4.使用Mockito编码完成接口测试
- 2.5. 使用Swagger2构建API文档
- 2.6.接口文档多种格式导出离线阅读
- 2.7.Swagger3-即OpenAPI使用
- 第三章 spring boot 配置管理
- 3.1.结合源码讲解bean自动装配原理
- 3.2.详解YAML语法及占位符语法
- 3.3.YAML配置绑定变量两种方式
- 3.4.配置属性值数据绑定校验
- 3.5.加载额外配置文件的两种方式
- 3.6.使用SpEL表达式绑定配置项
- 3.7.profile不同环境使用不同配置
- 3.8.配置及配置文件的加载优先级
- 3.9.配置文件敏感字段加密
- 第四章 整合数据库开发框架
- 4.1.整合Spring JDBC操作数据
- 4.2 Spring JDBC多数据源的实现
- 4.3.Spring JDBC JTA实现分布式事务
- 4.4.主流ORM持久层框架选型
- 4.5.java bean的赋值转换
- 4.6.整合Spring Data JPA操作数据
- 4.6.1.SpringDataJPA实现分页排序
- 4.7.Spring data JPA的多数据源实现
- 4.8.JPA+atomikos实现分布式事务
- 4.9.1.整合MybatisGenerator操作数据
- 4.9.2.整合mybatisPlus操作数据库
- 4.10.Mybatis开发最佳实践总结
- 4.11.Spring mybatis的多数据源实现
- 4.12.1.mybatis+atomikos实现分布式事务
- 4.12.2.mybatisplus+atomikos实现分布式事务
- 4.13.Spring事务与分布式事务
- 4.14.一行代码实现RESTFul接口
- 4.15.一键生成数据库文档
- 第五章 整合静态资源与模板引擎
- 5.1.1.webjars与静态资源
- 5.1.2.访问jar内部静态资源
- 5.2.模板引擎选型与未来趋势
- 5.3.web应用开发之整合jsp
- 5.4.web应用开发之整合freemarker
- 5.5.web应用开发之整合thymeleaf
- 5.6.thymeleaf基础语法讲解
- 5.7.thymeleaf内置对象与工具类
- 5.8.公共片段(标签)与内联js
- 第六章 生命周期内的拦截过滤与监听
- 6.1.Servlet域对象与属性变化监听
- 6.2.Servlet过滤器的实现
- 6.3.spring拦截器及请求链路说明
- 6.4.自定义事件的发布与监听
- 6.5.应用启动的监听
- 6.6.类初始化监听
- 第七章 嵌入式容器的配置与应用
- 7.1.嵌入式容器的运行参数配置
- 7.2.为Web容器配置HTTPS
- 7.3.切换到jetty&undertow容器
- 7.4.打war包部署到外置tomcat容器
- 第八章 统一全局异常处理
- 8.1.设计一个优秀的异常处理机制
- 8.2.自定义异常和相关数据结构
- 8.3.通用全局异常处理逻辑
- 8.4.服务端数据校验异常处理逻辑
- 8.5.AOP完美处理页面跳转异常
- 第九章 日志框架与全局日志管理
- 9.1.日志框架的体系结构
- 9.2.logback日志框架配置
- 9.3.1.log4j2日志框架整合与使用
- 9.3.2.log4j2异步日志配置
- 9.4.拦截器实现统一访问日志
- 第十章 异步任务与定时任务
- 10.1.实现Async异步任务
- 10.2.为异步任务规划线程池
- 10.3.通过@Scheduled实现定时任务
- 10.4.quartz简单定时任务(内存持久化)
- 10.5.quartz动态定时任务(数据库持久化)
- 10.6.可观测异步任务线程池
- 第十一章 redis缓存与session共享
- 11.1.使用docker安装redis
- 11.2.redis数据结构与应用场景
- 11.3.单例哨兵及集群模式整合
- 11.4.使用redisTemplate操作数据
- 11.5.使用Redis Repository操作数据
- 11.6.spring cache缓存基本用法
- 11.7.1.详述缓存声明式注解的使用
- 11.7.2.EhCache缓存
- 11.8.缓存雪崩穿透等解决方案
- 11.9.集群多节点应用session共享
- 11.10.介绍redis分布式锁
- 11.11.RedisLockRegistry分布式锁
- 11.12.使用redisson实现分布式锁
- 第十二章 整合分布式文件系统
- 12.1.文件本地上传与提供访问服务
- 12.2.MinIO简介与选型介绍
- 12.3.MinIO的安装与基础用法
- 12.4.整合MinIO的JavaSDK
- 12.5.fastdfs简介及架构说明
- 12.6.使用docker安装fastdfs
- 12.7.开发一个自定义fastdfs-starter
- 12.8.整合fastdfs操作文件数据
- 第十三章 服务器推送技术
- 13.1.主流服务器推送技术说明
- 13.2.服务端推送事件SSE
- 13.3.双向实时通信websocket
- 第十四章 邮件发送的整合与使用
- 14.1.基础协议及邮件配置整合
- 14.2.发送html和基于模板的邮件
- 14.3.发送带附件和内联附件邮件
- 第十五章 应用程序监控管理
- 15.1.Actuator应用监控快速入门
- 15.2.Actuator服务保护缓存及跨域
- 15.3.SpringBootAdmin界面化监控
- 第十六章 消息队列的整合与使用
- 16.1.消息队列与JMS规范简介
- 16.2.使用docker安装activeMQ
- 16.3.activeMQ实现点对点队列
- 16.4.activeMQ实现发布订阅队列
- 16.5.docker安装RocketMQ
- 16.6.RocketMQ实现2种消费模式
- WebFlux文档迁移的说明
- 番外篇:周边技术生态
- centos7安装docker图文详解
- docker安装mongodb(单点)图文详解
- 整合Spring data mongodb操作数据
- windows下如何安装git
- springboot非web项目构建
- 多种方式shutdown应用服务
- SpringBoot-2.2版本的变化
- SpringBoot中如何使用Cookies
- 使用flyway管理数据库版本
- SpringBoot解决跨域访问的问题
- IDEA远程调试linux上的SB项目
- 附录一:mybatis-plus
- f1-1.CURD快速入门
- f1-2.条件构造器使用与总结
- f1-3.自定义SQL
- f1-4.表格分页与下拉分页查询
- f1-5.ActiveRecord模式
- f1-6.主键生成策略
- f1-7.MybatisPlus代码生成器
- f1-8.逻辑删除
- f1-9.字段自动填充
- f1-10.多租户解决方案
- f1-11 日志打印输出
- 附录二:RestTemplate
- f2-1.基本介绍及配置使用
- f2-2.底层HTTP客户端库的切换
- f2-3.GET请求使用详解
- f2-4.POST请求使用详解
- f2-5.HTTP method使用方法详解
- f2-6.文件上传与下载
- f2-7.请求失败异常处理
- f2-8.自动重试机制
- f2-9.通过BasicAuth认证
- f2-10使用代理作为跳板