CORS与CSRF在Spring Security中的使用
背景
在项目使用了Spring Security之后,很多接口无法访问了,从浏览器的网络调试窗看到的是CORS的报错和403的报错

分析
我们先来看一下CORS是什么,和它很相似的CSRF是什么,在SpringSecurity中如何配置以及起的什么作用
CORS(Cross Origin Resource Sharing)
CORS跨域资源分享,是一种机制,通过在HTTP响应头中加入特定字段限制不同域的资源请求
跨源HTTP请求的一个例子:运行在 https://domain-a.com 的 JavaScript 代码使用 XMLHttpRequest 来发起一个到 https://domain-b.com/data.json 的请求
出于安全性,浏览器限制脚本内发起的跨源HTTP请求,而CORS就是用来允许跨源请求的
用法
用法: 在服务端的响应头(Header)中增加以下字段
| Header | 含义 | 例子 |
|---|---|---|
| Access-Control-Allow-Origin | 指定了允许访问该资源的外域 URI | https://mozilla.org或者* |
| Access-Control-Expose-Headers | 让服务器把允许浏览器访问的头放入白名单 | X-My-Custom-Header, X-Another-Custom-Header |
| Access-Control-Max-Age | 指定了preflight请求的结果能够被缓存多久 | |
| Access-Control-Allow-Credentials | 当浏览器的 credentials 设置为 true 时是否允许浏览器读取 response 的内容 | true |
| Access-Control-Allow-Methods | 允许哪些方法 | GET、POST |
| Access-Control-Allow-Methods | 允许哪些Header |
代码非常简单,有现成的两种方式
SpringMVC
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CrossConfig implements WebMvcConfigurer{
@Override
public void addCorsMappings( CorsRegistry registry ){
registry.addMapping( "/**" )
.allowedOrigins( "*" )
.allowedMethods( "GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS" )
.allowCredentials( true ).maxAge( 3600 ).allowedHeaders( "*" );
}
}
Spring Security
在Spring Security配置类中加入
@Bean
public CorsConfigurationSource corsConfigurationSource(){
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins( Collections.singletonList( "*" ) );
configuration.setAllowedMethods( Arrays.asList( "GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS" ) );
configuration.setAllowCredentials( true );
configuration.setAllowedHeaders( Collections.singletonList( "*" ) );
configuration.setMaxAge( 3600L );
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration( "/**", configuration );
return source;
}
注意
- 自己写过滤器也行,总之把这些Header加入响应就行
- 上面代码的策略非常宽松,可以适当限制域名保证安全
Spring Security和SpringMVC的CORS冲突
Spring Security是用访问认证是过滤器来实现的
SpringMVC的CORS是用拦截器来实现的,参考SpringBoot中addCorsMappings配置跨域与拦截器互斥问题的原因研究,其中写入响应头的类是org.springframework.web.cors.DefaultCorsProcessor
当存在Spring Security时,会存在加不上响应头的现象,因为在过滤器阶段可能因为认证不通过被拒绝了,所以当存在Spring Security的时候使用Spring Security的CORS用法就行
CSRF(Cross Site Request Forgery)
CSRF跨站请求伪造,是一种web攻击手段,通过向服务器发送伪造请求,进行恶意行为的攻击手段
举个例子,你登录了A网站,浏览器会记录A网站的登录Cookie,下次访问就不会重新登录了,而此时你访问了B网站,网站的网页携带一个恶意JS脚本,其中的内容是获取或更改你A网站的信息,此时浏览器会自动的把Cookie带上,A网站会认为这个请求是你本人的操作,CSRF就是用来防范这种攻击的
如何防范
Spring Security的方式是在表单上面生成一个csrf_token, 提交表单的时候去验证,因为第三方网站是没有这个token的,所以提交不成功
无状态应用
如这篇文章A Guide to CSRF Protection in Spring Security所说:
If our stateless API uses token-based authentication, like JWT, we don't need CSRF protection and we must disable it as we saw earlier.
使用JWT无状态应用是不需要csrf保护的,因为JWT不使用cookie, 具体参考如何通过JWT防御CSRF
Spring Security关闭csrf
其中的csrf().disable()
@Override
protected void configure( HttpSecurity http ) throws Exception{
http
.cors()
.and()
.csrf()
.disable()
.sessionManagement()
.and()
.authorizeRequests()
.anyRequest()
.permitAll()
.and()
.exceptionHandling()
.accessDeniedHandler( new SimpleAccessDeniedHandler() );
}
Set-Cookie问题
解决了cors的问题之后,再访问Spring Security需要认证的URL时,还是出现403错误

看下save的请求头,没有带上cookie

userinfo接口是登录接口,响应头包含了Set-Cookie,看起来没有生效, 而且能确认是前端的问题

解决方法
通过修改前端axios配置, 增加withCredentials: true
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API2,
withCredentials: true,
transformResponse: [function (data) {
try {
return JSONBig.parse(data)
} catch (err) {
return data
}
}],
timeout: 20000 // request timeout
})
参考
SpringBoot中addCorsMappings配置跨域与拦截器互斥问题的原因研究
CORS与CSRF在Spring Security中的使用的更多相关文章
- Spring Security 中的过滤器
本文基于 spring-security-core-5.1.1 和 tomcat-embed-core-9.0.12. Spring Security 的本质是一个过滤器链(filter chain) ...
- 六:Spring Security 中使用 JWT
Spring Security 中使用 JWT 1.无状态登录 1.1 什么是有状态? 1.2 什么是无状态 1.3 如何实现无状态 2.JWT 2.1 JWT数据格式 2.2 JWT交互流程 2.3 ...
- 五:Spring Security 中的角色继承问题
Spring Security 中的角色继承问题 以前的写法 现在的写法 源码分析 SpringSecurity 在角色继承上有两种不同的写法,在 Spring Boot2.0.8(对应 Spring ...
- [收藏]Spring Security中的ACL
ACL即访问控制列表(Access Controller List),它是用来做细粒度权限控制所用的一种权限模型.对ACL最简单的描述就是两个业务员,每个人只能查看操作自己签的合同,而不能看到对方的合 ...
- Spring Security中html页面设置hasRole无效的问题
Spring Security中html页面设置hasRole无效的问题 一.前言 学了几天的spring Security,偶然发现的hasRole和hasAnyAuthority的区别.当然,可能 ...
- Spring Security 中的 Bcrypt
最近在写用户管理相关的微服务,其中比较重要的问题是如何保存用户的密码,加盐哈希是一种常见的做法.知乎上有个问题大家可以先读一下: 加盐密码保存的最通用方法是? 对于每个用户的密码,都应该使用独一无二的 ...
- 浅谈使用spring security中的BCryptPasswordEncoder方法对密码进行加密与密码匹配
浅谈使用springsecurity中的BCryptPasswordEncoder方法对密码进行加密(encode)与密码匹配(matches) spring security中的BCryptPass ...
- 看源码,重新审视Spring Security中的角色(roles)是怎么回事
在网上看见不少的博客.技术文章,发现大家对于Spring Security中的角色(roles)存在较大的误解,最大的误解就是没有搞清楚其中角色和权限的差别(好多人在学习Spring Security ...
- Spring Security中实现微信网页授权
微信公众号提供了微信支付.微信优惠券.微信H5红包.微信红包封面等等促销工具来帮助我们的应用拉新保活.但是这些福利要想正确地发放到用户的手里就必须拿到用户特定的(微信应用)微信标识openid甚至是用 ...
- spring boot跨域请求访问配置以及spring security中配置失效的原理解析
一.同源策略 同源策略[same origin policy]是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源. 同源策略是浏览器安全的基石. 什么是源 源[orig ...
随机推荐
- Elasticsearch:Elasticsearch-head - 用于浏览和与 Elasticsearch 集群进行交互的 Web 前端
文章转载自:https://elasticstack.blog.csdn.net/article/details/114575256 离线安装方式:https://www.cnblogs.com/sa ...
- 1-VSCode搭建GD32开发环境
一.使用VSCode开发GD32的原因 1-单片机开发用的最多的IDE为Keil,而Keil为商用软件,并非开源,而且只支持windows环境,介于当前关系,有断供的风险在. 2-其他IDE类似第1条 ...
- 《HelloGitHub》第 78 期
兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣.入门级的开源项目. https://github.com/521xueweiha ...
- vue2.x引入threejs
@ 目录 vue2.x引入threejs npm安装 使用指定版本: 其他插件 实例 强调 vue2.x引入threejs npm安装 npm install three 使用指定版本: npm in ...
- 垃圾回收机制GC
垃圾回收机制GC 我们已经知道,name = 'leethon'这一赋值变量的操作,是将变量与数据值相绑定. 而数据值是存储到内存中的,有时变量会重新赋值即绑定其他数据值,而使得原本的数据值无法通过变 ...
- Java注解(1):码农的小秘
很多码农在写代码的时候不太爱写注释,结果任务一多,时间一长,需求一改,就完全不知道当初自己都干了些啥了.好在现在大多数编程语言都有注释功能,能够在代码里面做一些备注,不至于时间长了忘掉.但这些注释只是 ...
- How to get the return value of the setTimeout inner function in js All In One
How to get the return value of the setTimeout inner function in js All In One 在 js 中如何获取 setTimeout ...
- 面向对象day1,创建类和对象时,对象内存是在哪
上面我创建了两个类,一个是测试类,在测试包里面,一个是生产类,在src文件里面.可以看到,调用类里面的对象的时候需要先创建一个对象,然后通过对象来调用类里面的属性和方法等,但是这个时候我得先记录一下, ...
- 前端开发日常——CSS动画无限轮播
近来没有什么值得写的东西,空闲的时候帮前端的同学做了些大屏上的展示模块,就放在这里写写吧,手把手"需求->设计-> 实现",受众偏新手向. 为了直观便于理解, 直接把结 ...
- Linux基础_4_文件夹管理
文件路径 . #表示当前目录,同./ .. #表示上级目录,同../ ../../ #表示上上级目录 / #表示根目录 注:文件名长度不超过255个字符 注:.开头为隐藏文件 切换目录 cd #默认切 ...