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 ...
随机推荐
- DevExpress弹框、右键菜单、Grid的使用
很重要!!!Dev为了区分winform的命名,会把一些新添加的属性放在Properties对象里!!找不到想要的属性,记得到里面找找哦! 一.下拉框 在这里假设我们的数据源是db.List(),在这 ...
- 文盘Rust -- struct 中的生命周期
最近在用rust 写一个redis的数据校验工具.redis-rs中具备 redis::ConnectionLike trait,借助它可以较好的来抽象校验过程.在开发中,不免要定义struct 中的 ...
- 二手商城集成jwt认证授权
------------恢复内容开始------------ 使用jwt进行认证授权的主要流程 参考博客(https://www.cnblogs.com/RayWang/p/9536524.html) ...
- 1、使用简单工厂模式设计能够实现包含加法(+)、减法(-)、乘法(*)、除法(/)四种运算的计算机程序,要求输入两个数和运算符,得到运算结果。要求使用相关的工具绘制UML类图并严格按照类图的设计编写程
1.使用简单工厂模式设计能够实现包含加法(+).减法(-).乘法(*).除法(/)四种运算的计算机程序,要求输入两个数和运算符,得到运算结果.要求使用相关的工具绘制UML类图并严格按照类图的设计编写程 ...
- python制作一个小型翻译软件
from urllib import parse,request import requests,re,execjs,json,time 英语查词翻译 class Tencent(): def ini ...
- LcdTools如何编写MIPI指令(初始化代码)
在LcdTools帮助文档中查看MIPI读写指令描述,如下图 编写LCM初始化代码就是配置LCM Driver IC寄存器值,一般只需用MipiWrite()指令写参数即可:下面介绍MipiWrite ...
- 有用的内置Node.js APIs
前言 在构建你的第一个Node.js应用程序时,了解node开箱即用的实用工具和API是很有帮助的,可以帮助解决常见的用例和开发需求. 有用的Node.js APIs Process:检索有关环境变量 ...
- 图数据 3D 可视化在 Explorer 中的应用
本文首发于 NebulaGraph 公众号 前言图数据可视化是现代 Web 可视化技术中比较常见的一种展示方式,NebulaGraph Explorer 作为基于 NebulaGraph 的可视化产品 ...
- 说说switch关键字
Switch语法 switch作为Java内置关键字,却在项目中真正使用的比较少.关于switch,还是有那么一些奥秘的. 要什么switch,我有if-else 确实,项目中使用switch比较少的 ...
- Java使用lamda表达式简化代码
代码,自然写的越简洁越好啦,写的人舒服,看的人也舒服,一切为了高效. 要把有限的时间花到其它有意思的事情上去. 目的 学习简化代码的思路,使用jdk8新特性lamada表达式. 使用 某接口,只有一个 ...