csrf spring_无状态Spring安全性第1部分:无状态CSRF保护

csrf spring

如今,随着RESTful架构变得越来越标准,可能值得花一些时间重新考虑当前的安全方法。 在这一小系列博客文章中,我们将探索以无状态方式解决与Web相关的安全性问题的几种相对较新的方法。 这第一篇文章是关于保护您的网站免受跨站请求伪造(CSRF)的攻击。

回顾:什么是跨站请求伪造?

CSRF攻击基于挥之不去的身份验证Cookie。 在登录或以其他方式标识为网站上的唯一访问者之后,该网站可能会在浏览器中留下cookie。 如果没有显式注销或以其他方式删除此cookie,它可能会保持一段时间有效。

另一个站点可以通过使浏览器向受攻击的站点发出(跨站点)请求来滥用此功能。 例如,包括一些用于在“ http://siteunderattack.com/changepassword?pw=hacked”标签上进行POST的Javascript,将使浏览器发出该请求,并将对该域仍然有效的任何(身份验证)cookie附加到该请求!

即使单源策略(SOP)不允许恶意站点访问响应的任何部分。 从上面的示例中可以很明显地看出,如果请求的URL在后台触发任何副作用(状态更改),则损害已经完成。

常用方法

常用的解决方案是引入所谓的共享秘密CSRF令牌的要求,并将其作为先前响应的一部分让客户端知道。
然后,对于任何有副作用的请求,客户端都需要将其ping回服务器。 可以直接在表单中作为隐藏字段或作为自定义HTTP标头完成此操作。 无论哪种方式,其他站点都无法成功产生包含正确的CSRF令牌的请求,因为SOP阻止跨站点读取来自服务器的响应。 这种方法的问题在于服务器需要记住会话中每个用户的每个CSRF令牌的值。

无状态方法

1.切换到完整且设计正确的基于JSON的REST API。

单源策略仅允许跨站点的HEAD / GET和POST。 POST只能是以下哑剧类型之一:application / x-www-form-urlencoded,multipart / form-data或text / plain。 确实没有JSON! 现在考虑到GET永远不要在任何经过​​适当设计的基于HTTP的API中触发副作用,这让您可以简单地禁止任何非JSON POST / PUT / DELETE,一切都很好。 对于上传文件(多部分/表单数据)的方案,仍然需要明确的CSRF保护。

2.检查HTTP Referer标头。

通过检查仍然易受攻击的场景(例如多部分/表单数据POST)的Referer标头的存在和内容,可以进一步完善上述方法。 浏览器使用此标头来指定触发请求的确切页面(url)。 这可以轻松地用于检查站点的预期域。 请注意,如果选择进行此类检查,则在没有标题的情况下,切勿允许请求。

3.客户端生成的CSRF令牌。

让客户端在Cookie和自定义HTTP标头中生成并发送相同的唯一秘密值。 考虑到仅允许网站为其自己的域读取/写入Cookie,因此只有真实网站才能在两个标头中发送相同的值。 使用这种方法,您的服务器要做的就是在每个请求无状态的基础上检查两个值是否相等!

实作

着眼于第三种方法,用于基于显式但无状态CSRF令牌的安全性,让我们看看使用Spring Boot和Spring Security在代码中的样子。

在Spring Boot中,您会获得一些不错的默认安全设置,您可以使用自己的配置适配器对其进行微调。 在这种情况下,所需要做的就是禁用默认的csrf行为并添加自己的StatelessCSRFFilter:

自定义CSRF保护

@EnableWebSecurity
@Order(1)
public class StatelessCSRFSecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().addFilterBefore(new StatelessCSRFFilter(), CsrfFilter.class);}
}

这是StatelessCSRFFilter的实现:

自定义CSRF过滤器

public class StatelessCSRFFilter extends OncePerRequestFilter {private static final String CSRF_TOKEN = "CSRF-TOKEN";private static final String X_CSRF_TOKEN = "X-CSRF-TOKEN";private final RequestMatcher requireCsrfProtectionMatcher = new DefaultRequiresCsrfMatcher();private final AccessDeniedHandler accessDeniedHandler = new AccessDeniedHandlerImpl();@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {if (requireCsrfProtectionMatcher.matches(request)) {final String csrfTokenValue = request.getHeader(X_CSRF_TOKEN);final Cookie[] cookies = request.getCookies();String csrfCookieValue = null;if (cookies != null) {for (Cookie cookie : cookies) {if (cookie.getName().equals(CSRF_TOKEN)) {csrfCookieValue = cookie.getValue();}}}if (csrfTokenValue == null || !csrfTokenValue.equals(csrfCookieValue)) {accessDeniedHandler.handle(request, response, new AccessDeniedException("Missing or non-matching CSRF-token"));return;}}filterChain.doFilter(request, response);}public static final class DefaultRequiresCsrfMatcher implements RequestMatcher {private final Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");@Overridepublic boolean matches(HttpServletRequest request) {return !allowedMethods.matcher(request.getMethod()).matches();}}
}

不出所料,无状态版本在两个标头值上只做一个简单的equals()。

客户端实施

客户端实现也很简单,尤其是在使用AngularJS时。 AngularJS已经提供了内置的CSRF令牌支持。 如果您告诉它要读取的Cookie,它将自动将其值发送到您选择的自定义标头中。 (浏览器负责发送cookie标头本身。)

您可以按以下方式覆盖AngularJS的默认名称(XSRF而不是CSRF):

设置适当的令牌名称

$http.defaults.xsrfHeaderName = 'X-CSRF-TOKEN';
$http.defaults.xsrfCookieName = 'CSRF-TOKEN';

此外,如果您想为每个请求生成一个新的令牌值,则可以向$ httpProvider添加自定义拦截器,如下所示:

拦截器生成cookie

app.config(['$httpProvider', function($httpProvider) {//fancy random token, losely after https://gist.github.com/jed/982883function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e16]+1e16).replace(/[01]/g,b)};$httpProvider.interceptors.push(function() {return {'request': function(response) {// put a new random secret into our CSRF-TOKEN Cookie before each requestdocument.cookie = 'CSRF-TOKEN=' + b();return response;}};});    
}]);

您可以在github上找到一个完整的可用示例。
确保已安装gradle 2.0,并使用“ gradle build”和“ gradle run”简单地运行它。 如果要像eclipse一样在IDE中使用它,请使用“ gradle eclipse”,然后从IDE内导入并运行它(不需要服务器)。

免责声明

有时,经典的CSRF令牌被错误地视为针对重播或暴力攻击的解决方案。 此处列出的无状态方法未涵盖此类攻击。 我个人认为这两种类型的攻击都应该在另一个层次上进行处理,例如使用https和速率限制。 对于公开网站上的任何数据输入,我俩都认为这是必须的!

翻译自: https://www.javacodegeeks.com/2014/10/stateless-spring-security-part-1-stateless-csrf-protection.html

csrf spring

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/339186.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python网络编程项目_python网络编程详解

最近在看《UNIX网络编程 卷1》和《FREEBSD操作系统设计与实现》这两本书,我重点关注了TCP协议相关的内容,结合自己后台开发的经验,写下这篇文章,一方面是为了帮助有需要的人,更重要的是方便自己整理思路,加…

C - 指针总结

指针是什么?指针是一变量或函数的内存地址,是一个无符号整数,它是以系统寻址范围为取值范围,32位,4字节。指针变量:存放地址的变量。在C 中,指针变量只有有了明确的指向才有意义。指针类型int* …

android网络转圈,android基于dialog加载时转圈圈很好的demo

【实例简介】这是一个android基于dialog加载时转圈圈很好的完整demo,很适合新手学习,希望对有需要的朋友能得到帮助【实例截图】【核心代码】dialog_anim└── dialog_anim├── AndroidManifest.xml├── bin│ ├── AndroidManifest.xml│ ├…

spring期刊状态_无状态Spring安全性第2部分:无状态认证

spring期刊状态Spring Stateless Security系列的第二部分是关于以无状态方式探索身份验证的方法。 如果您错过了有关CSRF的第一部分,可以在这里找到。 因此,在谈论身份验证时,其全部内容就是让客户端以可验证的方式向服务器标识自己。 通常&…

分享10个值得关注的C语言开源项目

来源于网络,如有侵权,告知必删。

python3 x默认使用的编码_python3默认使用什么编码

python3默认编码为unicode,由str类型进行表示。二进制数据使用byte类型表示。 字符串通过编码转换成字节码,字节码通过解码成为字符串encode:str --> bytes(推荐学习:Python视频教程) decode&#xff1a…

html中写css代码,开发DIV CSS时 先写CSS代码还是先写HTML代码

相信良多LOVE用DIVCSS技术启示重构网页的爱好者友好,在起源学习DIVCSS的时分都邑想一个标题,想晓得DIVCSS妙手或有教育者在开发制作html页面的时刻,下场是先写html照样先写css?带着这…

象棋子 设计模式_通过设计国际象棋游戏了解策略模式

象棋子 设计模式今天,我们将借助一个示例来尝试了解策略模式。 我们将考虑的示例是国际象棋游戏。 这里的目的是解释策略模式,而不是构建全面的国际象棋游戏解决方案。 策略模式:策略模式被称为行为模式–用于管理对象之间的算法&#xff0…

入门C语言10问10答

1 如何理解变量与常量?变量与常量相当于数据的可读可写与只读,常量是数据的一种保护机制。在内存分配给程序的内存块中有专门的常量(只读)存储区。2 整型数据的溢出问题任何一种数据类型的数据在计算机中都有它确定的数值表示范围&#xff0…

mac json格式化工具_简洁好用的工具都是相似的

大家好,我是你们的章鱼猫。不知道大家了不了解 jq 这个工具呢?指的不是 JQuery,而是一个命令行工具。jq 是一个轻量级而且灵活的命令行 JSON 解析器,类似用于 JSON 数据的 sed 工具。我们来看一下使用 jq 处理 json 的基本用法(更…

android 撑满剩余空间,怎么让LinearLayout占据父布局的所有剩余空间

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼xmlns:tools"http://schemas.android.com/tools"android:layout_width"match_parent"android:layout_height"match_parent"android:paddingBottom"dimen/activity_vertical_margin"androi…

战神4 幕后花絮 概念艺术_Java 9幕后花絮:新功能从何而来?

战神4 幕后花絮 概念艺术找出Java幕后发生的事情,以及新功能如何实现 在上一篇文章中,我们介绍了即将发布的Java 9版本的新功能和尚待解决的功能,并简要提到了将新功能添加到下一个版本之前要经历的过程。 由于此过程几乎影响了所有Java开发人…

ID生成器 雪花算法

背景:在很多业务场景下,我们都需要一个唯一的 ID 来进行一些数据的交互,那么如何生成这个唯一的 ID 呢?如果在单机的情况下,生成唯一ID,可以利用机器内存的特点,通过内存分配即可。但我们线上的…

2014 android 机型排行,2014年10月十佳Android系统智能安卓手机排行榜单 Note 4第一名...

Android系统手机经过几年的发展,如今已经成了大家购机的首选。但在市面上数量众多的Android家族成员中,那些才是真正值得期待和拥有的机型,或许每个人会有不同的答案。如果你还在几款机型的选择上纠结,那么不妨借助国外媒体Androi…

python anaconda安装_Python - 安装并配置Anaconda环境

$ py --version # 当前默认python版本 Python 3.7.1 $ conda create --name testpy2 python2.7 pandas # 创建名为testpy2的运行环境,并安装pandas包及其依赖包 Solving environment: done ## Package Plan ## environment location: D:\DownLoadFiles\anaconda3\en…

jstack调试_增压的jstack:如何以100mph的速度调试服务器

jstack调试使用jstack调试实时Java生产服务器的指南 jstack就像U2一样-从时间的黎明就一直在我们身边,我们似乎无法摆脱它 。 除了笑话,到目前为止,jstack是您的工具库中用于调试实时生产服务器的最方便的工具之一。 即便如此,我仍…

C/C 输入输出缓冲区

【导读】:本文介绍C与C 输入输出缓冲的一些操作与特性。以下是正文(1)c 中cin、cout,cerr和c的stdin、stdout、stderr都是同步的,即iostream 对象和 and cstdio流是同步的,同步关系如下:同步即表…

android 活动销毁不了,即使活动已经销毁,AsyncTask也不会停止

我想添加一个信息补充,并给出一个指向库或2的指针,可以用于长时间运行的AsyncTask,甚至可以用于面向网络的asynctasks。AsyncTasks专为在后台执行操作而设计。是的,您可以使用该cancel方法停止它。当您从Internet下载内容时&#…

python输入input数组_python怎么输入数组

python怎么输入数组? python输入数组 一维数组:arr input("") //输入一个一维数组,每个数之间使空格隔开 num [int(n) for n in arr.split()] //将输入每个数以空格键隔开做成数组 print(num) //打印数组 一维数组输入输出示例&a…

eclipse 扩展_Eclipse扩展的轻量级集成测试

eclipse 扩展最近,我为Eclipse扩展点评估引入了一个小助手。 辅助程序努力减少通用编程步骤的样板代码,同时增加开发指导和可读性。 这篇文章是希望的后续文章,它显示了如何将实用程序与AssertJ定制断言结合使用,以编写针对Eclip…