展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > SpringBoot防御CSRF攻击的流程及原理是什么

SpringBoot防御CSRF攻击的流程及原理是什么

CSRF原理想要防御CSRF攻击,那我们需要先搞清楚什么是CSRF攻击,通过下面图例来和大家梳理CSRF攻击流程:其实这个流程很简单:1.假设用户打开了招商网上银行网站,并且登录。2.登录成功后,网上银行会返回Cookie给前端,浏览器将Cookie保存下来。3.用户在没有登出网上银行的情况下,在浏览器里打开了一个新的选项卡,然后又去访问了一个危险网站。4.这个危险网站上有一个超链接,超链接的地址指向了招商网上银行。4.用户点击了这个链接,由于这个超链接会自动携带上浏览器中保存的Cookie,所以用户不知

本文目录

    CSRF 原理

    想要防御 CSRF 攻击,那我们需要先搞清楚什么是 CSRF 攻击,通过下面图例来和大家梳理 CSRF 攻击流程:

    SpringBoot防御CSRF攻击的流程及原理是什么

    其实这个流程很简单:
    1.假设用户打开了招商网上银行网站,并且登录。
    2.登录成功后,网上银行会返回Cookie给前端,浏览器将Cookie保存下来。
    3.用户在没有登出网上银行的情况下,在浏览器里打开了一个新的选项卡,然后又去访问了一个危险网站。
    4.这个危险网站上有一个超链接,超链接的地址指向了招商网上银行。
    4.用户点击了这个链接,由于这个超链接会自动携带上浏览器中保存的Cookie,所以用户不知不觉中就访问了网上银行,进而可能给自己造成了损失。

    CSRF的流程大致就是这样,接下来用一个简单的例子展示一下CSRF到底是怎么一回事。

    CSRF实践

    1.我创建一个名为 csrf-mry 的 Spring Boot 项目,这个项目相当于我们上面所说的网上银行网站,创建项目时引入 Web 和 Spring Security依赖,如下:

    
    	
    		org.springframework.boot
    		spring-boot-starter-security
    	
    	
    		org.springframework.boot
    		spring-boot-starter-web
    	
    

    2.创建成功后,方便起见,我们直接将 Spring Security 用户名/密码 配置在 application.properties 文件中:

    server.port= 8866
    spring.security.user.name=javaboy
    spring.security.user.password=123

    3.然后我们提供两个测试接口

    package com.mry.csrf.controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RestController;
    @RestController
    public class CsrfDemoController {
        @PostMapping("/transfer")
        public void transferMoney(String name, Integer money) {
            System.out.println("name = " + name);
            System.out.println("money = " + money);
        }
        @GetMapping("/hello")
        public String hello() {
            return "hello";
        }
    }

    假设 /transfer 是一个转账接口(这里是假设,主要是给大家演示 CSRF 攻击,真实的转账接口比这复杂)。

    4.我们还需要配置一下 Spring Security,因为 Spring Security 中默认是可以自动防御 CSRF 攻击的,所以我们要把这个关闭掉。

    package com.mry.csrf.config;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().anyRequest().authenticated()
                    .and()
                    .formLogin()
                    .and()
                    .csrf()
                    .disable();
        }
    }

    配置完成后,我们启动 csrf-simulate-web 项目。

    5.我们再创建一个 csrf-loophole-web 项目,这个项目相当于是一个危险网站,为了方便,这里创建时我们只需要引入 web 依赖即可。
    项目创建成功后,首先修改项目端口:

    server.port= 8855

    6.然后我们在 resources/static 目录下创建一个 hello.html ,内容如下。

    
    
    
        
        Title
    
    
        
            
            
            
        
    
    

    这里有一个超链接,超链接的文本是点击查看美女图片,当你点击了超链接之后,会自动请求 http://localhost:8866/transfer 接口,同时隐藏域还携带了两个参数。

    配置完成后,就可以启动 csrf-loophole-web 项目了。

    接下来,用户首先访问 csrf-simulate-web 项目中的接口,在访问的时候需要登录,用户就执行了登录操作,访问完整后,用户并没有执行登出操作,然后用户访问 csrf-loophole-web 中的页面,看到了超链接,好奇这美女到底长啥样,一点击,结果钱就被人转走了。

    CSRF防御

    先来说说防御思路。

    CSRF 防御,一个核心思路就是在前端请求中,添加一个随机数。

    因为在 CSRF 攻击中,黑客网站其实是不知道用户的 Cookie 具体是什么的,他是让用户自己发送请求到网上银行这个网站的,因为这个过程会自动携带上 Cookie 中的信息。

    所以我们的防御思路是这样:用户在访问网上银行时,除了携带 Cookie 中的信息之外,还需要携带一个随机数,如果用户没有携带这个随机数,则网上银行网站会拒绝该请求。黑客网站诱导用户点击超链接时,会自动携带上 Cookie 中的信息,但是却不会自动携带随机数,这样就成功的避免掉 CSRF 攻击了。

    Spring Security 中对此提供了很好的支持,我们一起来看下。

    前后端不分离方案

    Spring Security 中默认实际上就提供了 csrf 防御,但是需要开发者做的事情比较多。
    首先我们来创建一个新的 Spring Boot 工程,创建时引入 Spring Security、Thymeleaf 和 web 依赖。

    1.pom信息

    
    	
    		org.springframework.boot
    		spring-boot-starter-web
    	
    	
    		org.springframework.boot
    		spring-boot-starter-security
    	
    	
    		org.springframework.boot
    		spring-boot-starter-thymeleaf
    	
    	
    		org.springframework.boot
    		spring-boot-starter-test
    		test
    	
    

    2.项目创建成功后,我们还是在 application.properties 中配置用户名/密码

    spring.security.user.name=mry
    spring.security.user.password=123456

    3.接下来,我们提供一个测试接口

    package com.mry.csrf.controller;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
    @RestController
    public class SecurityCsrfController {
        @PostMapping("/hello")
        @ResponseBody
        public String hello() {
            return "hello";
        }
    }

    注意,这个测试接口是一个 POST 请求,因为默认情况下,GET、HEAD、TRACE 以及 OPTIONS 是不需要验证 CSRF 攻击的。

    4.然后,我们在 resources/templates 目录下,新建一个 thymeleaf 模版

    
    
    
    
        
        Title
    
    
        
            
            
        
    
    

    注意,在发送 POST 请求的时候,还额外携带了一个隐藏域,隐藏域的 key 是 ${_csrf.parameterName},value 则是 ${_csrf.token}。

    这两个值服务端会自动带过来,我们只需要在前端渲染出来即可。

    5.接下来给前端 hello.html 页面添加一个控制器

    @GetMapping("/hello")
    public String hello2() {
    	return "hello";
    }

    6.添加完成后,启动项目,我们访问 hello 页面,在访问时候,需要先登录,登录成功之后,我们可以看到登录请求中也多了一个参数

    SpringBoot防御CSRF攻击的流程及原理是什么

    这里我们用了 Spring Security 的默认登录页面,如果大家使用自定义登录页面,可以参考上面 hello.html 的写法,通过一个隐藏域传递 _csrf 参数。

    访问到 hello 页面之后,再去点击【hello】按钮,就可以访问到 hello 接口了。

    SpringBoot防御CSRF攻击的流程及原理是什么

    这是 Spring Security 中默认的方案,通过 Model 将相关的数据带到前端来。

    如果你的项目是前后端不分项目,这种方案就可以了,如果你的项目是前后端分离项目,这种方案很明显不够用。

    前后端分离方案

    如果是前后端分离项目,Spring Security 也提供了解决方案。
    这次不是将 _csrf 放在 Model 中返回前端了,而是放在 Cookie 中返回前端,配置方式如下:

    package com.mry.csrf.config;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().anyRequest().authenticated()
                    .and()
                    .formLogin()
                    .and()
                    .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
        }
    }

    有小伙伴可能会说放在 Cookie 中不是又被黑客网站盗用了吗?其实不会的,大家注意如下两个问题:
    (1)黑客网站根本不知道你的 Cookie 里边存的啥,他也不需要知道,因为 CSRF 攻击是浏览器自动携带上 Cookie 中的数据的。
    (2)我们将服务端生成的随机数放在 Cookie 中,前端需要从 Cookie 中自己提取出来 _csrf 参数,然后拼接成参数传递给后端,单纯的将 Cookie 中的数据传到服务端是没用的。
    理解透了上面两点,你就会发现 _csrf 放在 Cookie 中是没有问题的,但是大家注意,配置的时候我们通过 withHttpOnlyFalse 方法获取了 CookieCsrfTokenRepository 的实例,该方法会设置 Cookie 中的 HttpOnly 属性为 false,也就是允许前端通过 js 操作 Cookie(否则你就没有办法获取到 _csrf)。

    配置完成后,重启项目,此时我们就发现返回的 Cookie 中多了一项:

    SpringBoot防御CSRF攻击的流程及原理是什么

    接下来,我们通过自定义登录页面,来看看前端要如何操作。

    首先我们在 resources/static 目录下新建一个 html 页面叫做 login.html:

    
    
    
        
        Title
        
        
    
    
    
                  

    这段 html 给大家解释一下:
    (1)首先引入 jquery 和 jquery.cookie ,方便我们一会操作 Cookie。
    (2)定义三个 input,前两个是用户名和密码,第三个是登录按钮。
    (3)点击登录按钮之后,我们先从 Cookie 中提取出 XSRF-TOKEN,这也就是我们要上传的 csrf 参数。
    (4)通过一个 POST 请求执行登录操作,注意携带上 _csrf 参数。

    服务端我们也稍作修改,如下:

    package com.mry.csrf.config;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.builders.WebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/static/js/**");
        }
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().anyRequest().authenticated()
                    .and()
                    .formLogin()
                    .loginPage("/login.html")
                    .successHandler((req,resp,authentication)->{
                        resp.getWriter().write("success");
                    })
                    .permitAll()
                    .and()
                    .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
        }
    }

    一方面这里给 js 文件放行。

    另一方面配置一下登录页面,以及登录成功的回调,这里简单期间,登录成功的回调我就给一个字符串就可以了。在登录成功后回调的详细解释。

    OK,所有事情做完之后,我们访问 login.html 页面,输入用户名密码进行登录,结果如下:

    SpringBoot防御CSRF攻击的流程及原理是什么

    可以看到,我们的 _csrf 配置已经生效了。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发
    相关文章 更多
    精品专题 更多
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    IOS软件

    正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

    AI

    正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

    Mac软件 更多
    Aperty macOS版
    Aperty macOS版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw macOS版
    AionClaw macOS版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy macOS版
    Loomy macOS版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirBuddy 3 macOS版
    AirBuddy 3 macOS版

    AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

    AirServer macOS版
    AirServer macOS版

    AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

    AnyDesk macOS版
    AnyDesk macOS版

    AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

    WINDOWS 更多
    讯飞绘文 网页版
    讯飞绘文 网页版

    讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

    Maya(Autodesk Maya) Windows版
    Maya(Autodesk Maya) Windows版

    Autodesk Maya 是面向影视、电视、动画和游戏行业的专业三维制作软件,集多边形与 NURBS 建模、角色绑定、关键帧和动作捕捉动画、Bifrost 特效模拟、材质开发及 Arnold 渲染于一体,

    Aperty Windows版
    Aperty Windows版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw Windows版
    AionClaw Windows版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy Windows版
    Loomy Windows版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirServer Windows版
    AirServer Windows版

    AirServer Windows版可把电脑变成AirPlay、Google Cast和Miracast无线投屏接收端,适合会议演示、课堂教学及家庭大屏分享。发送设备通常无需另装客户端,并可同时接收和智能排列多个镜像会话。