跨域问题与SpringBoot解决方案

什么是跨域?
定义:浏览器从一个域名的网页取请求另一个域名下的东西。通俗点说,浏览器直接从A域访问B域中的资源是不被允许的,如果想要访问,就需要进行一步操作,这操作就叫“跨域”。例如,你从百度的页面,点击一个按钮,请求了新浪的一个接口,这就进行了跨域。不单单只有域名不同就是跨域,域名、端口、协议其一不同就是不同的域,请求资源需要跨域。
为什么要跨域?
为什么需要跨域,而不直接访问其他域下的资源呢?这是浏览器的限制,专业点说叫浏览器同源策略限制。主要是为了安全考虑。现在的安全框架,一般请求的时候header中不是都存个token嘛,你要是用这个token去正常访问A域下的东西是没问题的,然后又去访问了B域,结果阴差阳错的还带着这个token,那么B域,或者说B网站是不是就可以拿着你的token去A域下做点什么呢,这就相当危险了。所以浏览器加上了所谓的浏览器同源策略限制。但是为了我们真的需要从A域下访问B的资源(正常访问),就需要用到跨域,跨越这个限制了。
SpringBoot解决跨域问题
SpringBoot可以基于Cors解决跨域问题,Cors是一种机制,告诉我们的后台,哪边(origin )来的请求可以访问服务器的数据。
全局配置
配置实例如下:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600);
}
}
首先实现了WebMvcConfigurer 接口,WebMvcConfigurer 这个接口十分强大,里面还有很多可用的方法,在SpringBoot2.0里面可以解决WebMvcConfigurerAdapter曾经的部分任务。其中一个方法就是addCorsMappings(),是专门为开发人员解决跨域而诞生的接口。其中构造参数为CorsRegistry。
看下CorsRegistry源码,十分简单:
public class CorsRegistry {
private final List<CorsRegistration> registrations = new ArrayList<>();
public CorsRegistration addMapping(String pathPattern) {
CorsRegistration registration = new CorsRegistration(pathPattern);
this.registrations.add(registration);
return registration;
}
protected Map<String, CorsConfiguration> getCorsConfigurations() {
Map<String, CorsConfiguration> configs = new LinkedHashMap<>(this.registrations.size());
for (CorsRegistration registration : this.registrations) {
configs.put(registration.getPathPattern(), registration.getCorsConfiguration());
}
return configs;
}
}
可以看出CorsRegistry 有个属性registrations ,按道理可以根据不同的项目路径进行定制访问行为,但是我们示例直接将pathPattern 设置为 /**,也就是说已覆盖项目所有路径,只需要创建一个CorsRegistration就好。getCorsConfigurations(),这个方法是获取所有CorsConfiguration的Map集合,key值为传入路径pathPattern。
回到示例代码CorsConfig中,registry对象addMapping()增加完传入路径pathPattern之后,return了一个CorsRegistration对象,是进行更多的配置,看一下CorsRegistration的代码,看看我们能配些什么?
public class CorsRegistration {
//传入的路径
private final String pathPattern;
//配置信息实体类
private final CorsConfiguration config;
//构造方法
public CorsRegistration(String pathPattern) {
this.pathPattern = pathPattern;
//原生注释看到了一个 @CrossOrigin 这个注解,待会看看是什么
// Same implicit default values as the @CrossOrigin annotation + allows simple methods
this.config = new CorsConfiguration().applyPermitDefaultValues();
}
//允许哪些源网站访问,默认所有
public CorsRegistration allowedOrigins(String... origins) {
this.config.setAllowedOrigins(Arrays.asList(origins));
return this;
}
//允许何种方式访问,默认简单方式,即:GET,HEAD,POST
public CorsRegistration allowedMethods(String... methods) {
this.config.setAllowedMethods(Arrays.asList(methods));
return this;
}
//设置访问header,默认所有
public CorsRegistration allowedHeaders(String... headers) {
this.config.setAllowedHeaders(Arrays.asList(headers));
return this;
}
//设置response headers,默认没有(什么都不设置)
public CorsRegistration exposedHeaders(String... headers) {
this.config.setExposedHeaders(Arrays.asList(headers));
return this;
}
//是否浏览器应该发送credentials,例如cookies Access-Control-Allow-Credentials
public CorsRegistration allowCredentials(boolean allowCredentials) {
this.config.setAllowCredentials(allowCredentials);
return this;
}
//设置等待时间,默认1800秒
public CorsRegistration maxAge(long maxAge) {
this.config.setMaxAge(maxAge);
return this;
}
protected String getPathPattern() {
return this.pathPattern;
}
protected CorsConfiguration getCorsConfiguration() {
return this.config;
}
}
局部配置
刚才遇到一个@CrossOrigin这个注解,看看它是干什么的?
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
String[] DEFAULT_ORIGINS = { "*" };
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
String[] DEFAULT_ALLOWED_HEADERS = { "*" };
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
boolean DEFAULT_ALLOW_CREDENTIALS = false;
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
long DEFAULT_MAX_AGE = 1800
/**
* Alias for {@link #origins}.
*/
@AliasFor("origins")
String[] value() default {};
@AliasFor("value")
String[] origins() default {};
String[] allowedHeaders() default {};
String[] exposedHeaders() default {};
RequestMethod[] methods() default {};
String allowCredentials() default "";
long maxAge() default -1;
}
这个注解可以作用于方法或者类上,实现局部跨域,你会发现除了设置路径(因为没必要了,都定位到局部了)其他的参数与全局类似。
小结
SpringBoot可以基于Cors解决跨域问题,可以设置全局跨域,也可以实现局部跨域,灵活配置方便使用。
跨域问题与SpringBoot解决方案的更多相关文章
- 跨域原因及SpringBoot、Nginx跨域配置
目录 概述 简单请求 跨域解决方案 概述 SpringBoot跨域配置 Nginx跨域配置 概述 MDN文档 Cross-Origin Resource Sharing (CORS) 跨域的英文是Cr ...
- 【分布式系列】session跨域及单点登录解决方案
Cookie机制 Cookie技术是客户端的解决方案,Cookie就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息. ...
- ajax 跨域----好用的解决方案
一.前言 跨域这个词就一直以很高的频率在身边重复出现,一直到现在,已经调试过N个跨域相关的问题了! 但是感觉还是差了点什么,于是现在重新梳理了一下.个人见识有限,如有差错,请多多见谅 二.前言 关于跨 ...
- Web 跨域请求问题的解决方案- CORS 方案
1.什么是跨域 跨域是指跨域名的访问,以下情况都属于跨域: 跨域现象 实例 域名不相同 www.baidu.com与www.taobao 一级域名相同,但是端口不相同 www.baidu.com:80 ...
- 跨域资源共享(CORS)问题解决方案
CORS:Cross-Origin Resource Sharing(跨域资源共享) CORS被浏览器支持的版本情况如下:Chrome 3+.IE 8+.Firefox 3.5+.Opera 12+. ...
- ajax跨域问题及相关解决方案
1 什么是跨域 所谓的跨域是指浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器施加的安全限制. 所谓同源是指,域名,协议,端口均相同: 2 什么时候会存在跨域的问题 页面访问不同源 ...
- Web 跨域请求(OCRS) 前端解决方案
1.同源策略如下: URL 说明 是否允许通信 http://www.a.com/a.jshttp://www.a.com/b.js 同一域名下 允许 http://www.a.com/lab/a.j ...
- IE9(8)跨域(CORS)解决方案
HTML5中 XMLHttpRequest Level 2 的推出.可以通过在返回的HTTP请求头中加入 Access-Control-Allow-Origin 的设置,让浏览器支持对不同域的AJAX ...
- Ajax 跨域的几种解决方案
作者:黄轩链接:http://www.zhihu.com/question/19618769/answer/38934786来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处 ...
随机推荐
- kube-proxy详解
KUBE_LOGTOSTDERR="--logtostderr=true"KUBE_LOG_LEVEL="--v=4"NODE_HOSTNAME="- ...
- Python说文解字_Python之多任务_04
问:并发.并行.同步.异步.阻塞.非阻塞 答: 并发.并行: 并发是指一个时间段内(不是指的时间点),有几个程序在同一个CPU上运行,但是任意时刻只有一个程序在CPU上运行.对人类的时钟来说1秒钟能干 ...
- 开源PLM软件Aras详解七 在Aras的Method中如何引用外部DLL
在实际的项目中,Aras内部的方法可能并不能完全满足我们,比如Office的组件,就必须引入,那么在Aras内部的Method中,我们如何引入外部Dll文件 首先,我们新建一个Dll文件,简单的Dem ...
- 周末畅谈 | 我是如何在硅谷获得年薪30万美金Offer的?
本文讲述了一位硅谷软件工程师的面试经验,他分享了他如何在硅谷拿到最终30万美金年薪的Offer,原文摘自:https://blog.usejournal.com/how-i-negotiated-a- ...
- 吴裕雄--天生自然MySQL学习笔记:MySQL 删除数据库
使用普通用户登陆 MySQL 服务器,可能需要特定的权限来创建或者删除 MySQL 数据库,所以使用 root 用户登录,root 用户拥有最高权限. 在删除数据库过程中,务必要十分谨慎,因为在执行删 ...
- Windows如何设置指定的IP走专线?
很多时候在工作中难免有多重网络环境的情况,为了方便之间的互访,可能会用的VPN等虚拟专线,作为网络管理员,route命令是必会的基础技能. 我们一般连接到专线vpn以后,默认会启用远程网关,这样我们所 ...
- Python D9 学习
Python 设置环境 当安装好Python 后 在计算机的属性里面 高级语言设置 环境变量. 环境变量里面的path 更改为Python的 树目录 可以从计算机直接下达命令 打开Pytho ...
- 微信小程序官方示例 官方weui-wxss下载于安装 详解
1.小程序示例源码:https://github.com/wechat-miniprogram/miniprogram-demo 2.微信 weui下载地址:https://github.com/we ...
- IDEA忽略文件,防止git提交不想提交的文件
IDEA忽略文件,防止git提交不想提交的文件 方法一(只对没有add到仓库的文件有效): 方法二(只对没有add到仓库的文件有效): 在IDEA中安装.ignore插件.创建好了之后: 安装.git ...
- 基于Struts2开发公司职工管理系统 Java源码
开发环境: Windows操作系统 开发工具: MyEclipse+Jdk+Tomcat+MySql数据库 职工管理系统作为一种管理软件正在各公司中得到越来越广泛的应用,且已达到了良好效果. 运行效果 ...