spring security中的csrf防御原理(跨域请求伪造)

Spring Security 中的 CSRF(Cross-Site Request Forgery)攻击防御是非常重要的安全机制。在这个攻防机制中,Spring Security 通过在表单中添加或者 TkCooikeToken 的形式防御 CSRF 攻击,保障 Web 应用程序的安全。

CSRF 防御机制

CSRF 攻击利用用户在 Web 浏览器中处于登录状态的 Cookie 值,来发起伪造请求从而获取资源或者执行关键操作。Spring Security 通过如下两种方式来防御 CSRF 攻击:

  1. 添加 CSRF Token 到每个表单中:我们可以将 CSRF Token 添加到每个表单中,这样表单提交时就会同时提交这个 Token 和表单数据,并且服务器会判断这个 Token 是否有效,从而确认该请求是否合法。

  2. 利用 HttpOnly Cookie 和 Header:同时,我们也可以使用 HttpOnly Cookie,它会指定 Cookie 只能通过 Http 协议传输(即不能使用 JavaScript 访问),以及设置 CSRF Token 在 http response header 中,避免 CSRF 攻击者伪造 Http 请求。

添加 CSRF Token 到每个表单中

Spring Security 的 CSRF 保护默认是开启的,可以通过下面的配置控制是否需要开启保护:

spring.security.enabled: true

默认情况下,Spring Security 在渲染表单时,会自动在表单的隐藏字段(名称为 _csrf)中添加一个 Token:

<input type="hidden" name="_csrf" value="c6cac604-4c3f-47f2-8a20-c4471260bfe1">

同时,Spring Security 会在服务器端拦截请求,判断请求中的 _csrf 值是否和当前 Session 中的 _csrf 值一致,如果不一致,则视为 CSRF 攻击,请求被拒绝。

需要注意的是,在使用 Thymeleaf 模板引擎时,Spring Security 提供了一个方便的标签来生成 CSRF Token,即 th:csrf,示例如下:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="UTF-8" />
    <title>Blog</title>
  </head>
  <body>
    <form method="post" th:action="@{/create}">
      <input type="text" name="title" />
      <textarea name="content"></textarea>
      <button type="submit">Submit</button>
      <!-- 表单中添加了th:csrf标签 -->
      <input type="hidden" th:csrf="${_csrf.token}" />
    </form>
  </body>
</html>

利用 HttpOnly Cookie 和 Header

除了在表单中添加 CSRF Token 外,Spring Security 还支持利用 HttpOnly Cookie 和 Header 来防御 CSRF 攻击。

  1. HttpOnly Cookie

可以通过以下的配置为 CSRF Token 设置 HttpOnly Cookie:

spring.security.csrf.cookie.httpOnly: true

这样,Spring Security 会将 CSRF Token 放入到 HttpOnly Cookie 中,浏览器不能通过 JavaScript 访问此 Cookie,从而有效防止 CSRF 攻击者产生伪造请求。

可以通过如下的方式检查 HttpOnly Cookie:

HTTP/1.1 200 OK
Set-Cookie: csrf_token=ZJLWV3DGJA3L3GZH5A47BO54PABELPFE; Path=/; HttpOnly
  1. Header

可以通过以下的配置将 CSRF Token 作为 Header 发送到客户端:

spring.security.csrf.headerName:X-XSRF-TOKEN

客户端需要将获取到的 Token 在之后的请求头中发送到服务器,示例如下:

POST /api/saveUser HTTP/1.1
Host: example.com
X-XSRF-TOKEN: zWfB3yGnNTLuG98Vibpv
Content-Type: application/json
...

在服务器端,Spring Security 会解析 Header 中的 CSRF Token,与当前 Session 中的 CSRF Token 进行比较,如果不一致,则视为 CSRF 攻击,请求被拒绝。

示例1

原网站中含有一个表单页面,表单需要用户输入邮箱、密码信息,完成操作后登录。
恶意攻击者制作出一个 CSFR 攻击页面,页面中含有一个表单,表单中有两个隐藏的 input 输入框:邮箱、密码,这个表单即使用户没有登录到被攻击页面中,也可以正常提交数据。

攻击者送给用户一个欺骗性的 URL 地址,让用户误以为是正常用户登陆页面的地址,用户打开这个欺骗地址,就会看到一个假的登录页面;当表单中被提交的时候,被攻击者页面的邮箱和密码都被提交到他所指向的真正登录页面上,用户完成操作后就成为了攻击者的虚假账户。

防御机制:在表单中添加 CSRF Token。

假设网站服务器端是采用java spring boot框架进行开发的,那么需要使用类似于下面的代码,在后台使用Thymeleaf模板渲染数据并渲染CSRF Token

<form action="/login" method="post">
    <input type="text" name="email" placeholder="请输入邮箱" />
    <input type="password" name="password" placeholder="请输入密码" />
    <!-- 添加CSRF Token标签,名称为字段为 _csrf -->
    <input type="hidden" name="_csrf" value="${_csrf.token}"/>
    <button type="submit">登录</button>
</form>

示例2

当Web页面中有图片资源需要加载(通常是从一个不同的域加载),加载域的服务器里面存在漏洞,导致漏洞被攻击者利用,而这个图片会要求跨域读取一些需要保护的资源,这时候会涉及到CSRF攻击。

防御机制:使用 HttpOnly Cookie 和 Header。

假设服务器端是采用java spring boot框架的话,可以通过在 Security 配置文件中添加如下代码启用 HttpOnly Cookie 和 Header 防御 CSRF 攻击:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().ignoringAntMatchers("/api/**")
        .and()
         .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
        .and()
        .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
        .addFilterAfter(new CustomCsrfFilter(), CsrfFilter.class)
        .authorizeRequests()
        .antMatchers("/", "/home", "/about").permitAll()
        .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
        .antMatchers("/user/**").access("hasRole('ROLE_USER')")
        .anyRequest().authenticated();
}

其中,CookieCsrfTokenRepository.withHttpOnlyFalse()指定 CSRF Token 放置在 HttpOnly Cookie 中。可以在 Http Response Header 中看到以下信息:

HTTP/1.1 200 OK
Set-Cookie: XSRF-TOKEN=k8_6gux8JKyl7z4hmsEUU3hE5_FJXr5zf1ZcI7CntAg; Path=/

CsrfHeaderFilterCustomCsrfFilter 是为了拦截请求中的 CSRF Token,判断它是否与服务器端持有的 Token 一致,并对请求进行过滤。

public class CsrfHeaderFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
        if (csrf != null) {
            response.setHeader("X-CSRF-TOKEN", csrf.getToken());
        }
        filterChain.doFilter(request, response);
    }
}

public class CustomCsrfFilter extends OncePerRequestFilter {
    private final CsrfTokenRepository csrfTokenRepository;
    public CustomCsrfFilter(CsrfTokenRepository csrfTokenRepository) {
        this.csrfTokenRepository = csrfTokenRepository;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        CsrfToken csrfToken = csrfTokenRepository.loadToken(request); // 加载 CSRF Token
        if (csrfToken != null) {
            String csrfHeader = request.getHeader("X-CSRF-TOKEN"); // 获取请求中的 CSRF Token
            if (csrfHeader != null && !csrfToken.getToken().equals(csrfHeader)) {
                throw new ServletException("Invalid CSRF Token");
            }
        }
        filterChain.doFilter(request, response);
    }
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:spring security中的csrf防御原理(跨域请求伪造) - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • ASP中Session技巧 默认过期时间为20分钟

    ASP中的Session技巧是网站开发中常用的技术,通过使用Session,我们可以在不同的页面间共享数据和信息。在ASP中,Session的默认过期时间为20分钟,为了更好地利用Session技术并确保其正常运行,我们需要注意以下几点: 设置Session过期时间 为了避免Session失效,我们可以通过设置Session过期时间来保持Session的有效…

    Java 2023年6月15日
    00
  • JSP连接MySQL数据库详细步骤

    下面为您详细讲解JSP连接MySQL数据库的步骤。 1. 准备工作 在开始连接MySQL数据库之前,需要先进行准备工作: 安装MySQL数据库 下载MySQL的Java Connector(JDBC)驱动 2. 导入JDBC驱动包 将下载好的JDBC驱动包(.jar文件)导入到您的web项目中。您可以将该驱动包放置在WEB-INF/lib文件夹下,或者添加到…

    Java 2023年5月20日
    00
  • 解决springboot 部署到 weblogic 中 jar 包冲突的问题

    为了解决SpringBoot部署到WebLogic中Jar包冲突的问题,我们需要遵循以下步骤: 1. 排查Jar包冲突 在运行过程中,我们需要关注控制台输出的错误信息,尤其是关于Jar包冲突的信息。其中包含有关Arifact ID和Version的信息。使用Maven或Gradle构建项目时,我们需要检查项目的依赖关系(pom.xml或build.gradl…

    Java 2023年5月20日
    00
  • 反射调用private方法实践(php、java)

    让我详细讲解一下反射调用private方法的完整攻略。 什么是反射 反射是指在运行时获取一个类或对象的相关信息,比如属性、方法等,并可以动态调用这些方法和属性。反射是很强大的一个功能,在一些特殊的情况下,可以使用反射来实现一些普通的API所无法完成的功能。 反射调用private方法的步骤 如果要调用某个类中的private方法,可以借助PHP或Java的反…

    Java 2023年5月31日
    00
  • Tomcat 与 maven 的安装与使用教程

    Tomcat 与 Maven 的安装与使用教程 Tomcat 是一个常用的 Java Web 应用程序的部署容器,Maven 是一个常用的 Java 项目构建工具,在 Java 开发中两者经常被用到。下面是 Tomcat 和 Maven 的安装及使用教程。 1. 安装 Tomcat Tomcat 的官方网站是 http://tomcat.apache.org…

    Java 2023年5月19日
    00
  • eclipse创建springboot项目的三种方式总结

    在Eclipse中,我们可以使用以下三种方式来创建Spring Boot项目: 使用Spring Initializr创建项目 使用Eclipse自带的Spring Boot项目向导创建项目 使用Maven或Gradle创建项目 以下是每种方式的详细步骤和示例: 1. 使用Spring Initializr创建项目 步骤 打开Eclipse,选择File -…

    Java 2023年5月14日
    00
  • SpringMVC集成Web与MVC执行流程和数据响应及交互相关介绍全面总结

    以下是关于“SpringMVC集成Web与MVC执行流程和数据响应及交互相关介绍全面总结”的完整攻略,其中包含两个示例。 SpringMVC集成Web与MVC执行流程和数据响应及交互相关介绍全面总结 SpringMVC是一个基于MVC模式的Web框架,它提供了一种灵活、高效的方式来开发Web应用程序。在SpringMVC中,Web和MVC是如何集成的?Spr…

    Java 2023年5月16日
    00
  • 十五道tomcat面试题,为数不多的机会!

    下面我将分步骤介绍“十五道tomcat面试题,为数不多的机会!”的完整攻略。 一、了解Tomcat Tomcat是一个简单的、易于使用的Web服务器,也是一个Servlet容器。它是开源的,由Apache软件基金会维护。可以运行在Windows、Linux、Unix等多个平台上。 二、准备Tomcat面试题 为了确保你能顺利通过Tomcat的面试,你需要提前…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部