SpringSecurity跨域请求伪造(CSRF)的防护实现

为了防止SpringSecurity跨域请求伪造(CSRF)攻击,需要采取一些措施来进行防护实现。下面是实现CSRF防护的步骤:

1.同源检查

这是最常见的CSRF防护方法,包括验证请求的源(Origin),或者Referrer)与app地址是否相同,建议把这个配置在Spring Security中,只需在SpringSecurity的配置类中添加如下代码:

http.csrf().requireCsrfProtectionMatcher(new CSRFRequireSamesiteMatcher());

此处使用CSRFRequireSamesiteMatcher来进行same-site检测,这可以防止第三方站点进行CSRF攻击。如果源(Origin),或者Referrer)与app地址不同,spring security将拒绝该请求。

2.Token验证

在服务器端为每个用户生成一个随机的token,然后将其存储在session中,并在每个表单提交中包含一个隐藏的字段,包含Token。客户端使用该token作为表单参数,服务端进行校验。SpringSecurity已经集成了处理该场景的组件CsrfTokenRepository,你可以直接注入此组件并使用。 这个过程需要两个步骤:

2.1 将Token插入到所有表单

Springsecurity在JSP端预置了名为_csrf的Token字段,你只需要在jps的form中使用即可:

<form action="/login" method="post">
  <input type="text" name="username" />
  <input type="password" name="password" />
  <input type="submit" value="Login"/>
  <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>

在默认情况下,Spring Security的所有EndPoint或者controller都能够解析名为_csrf的token字段。

2.2 创建Token工厂和存储库

创建跨站点请求伪造保护所需的csrfTokenRepository Bean,详情请参考以下示例:

http.csrf()
    .csrfTokenRepository(csrfTokenRepository());

private CsrfTokenRepository csrfTokenRepository() {
    HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
    repository.setSessionAttributeName("_csrf");

    return repository;
}

此处使用了HttpSessionCsrfTokenRepository,用于将生成的token存储在当前用户的session中,如果Oauth2集成的话,使用的是OAuth2AuthorizedClientCsrfTokenRepository

以上便是Spring Security防护CSRF攻击的两种常见的方法。

示例1:

在Spring Security中使用CsrfToken进行跨站请求伪造保护:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/css/**", "/index").permitAll().antMatchers("/user/**")
                .hasRole("USER").and().formLogin().loginPage("/login").failureUrl("/login-error")
                .and().exceptionHandling().accessDeniedPage("/401");

        http.csrf().csrfTokenRepository(csrfTokenRepository());
    }

    private CsrfTokenRepository csrfTokenRepository() {
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setSessionAttributeName("_csrf");

        return repository;
    }
}

在JSP的表单中,将_csrf的Token属性作为隐藏的字段:

<form th:action="@{/logout}" method="post">
    <input type="submit" value="Log out" />
    <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
</form>

示例2:

在Spring Security中使用SameSite来防范跨站请求伪造攻击。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {  
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/css/**", "/index").permitAll().antMatchers("/user/**")
                .hasRole("USER").and().formLogin().loginPage("/login").failureUrl("/login-error")
                .and().exceptionHandling().accessDeniedPage("/401");

        http.csrf().requireCsrfProtectionMatcher(new CSRFRequireSamesiteMatcher());
    }
}

public class CSRFRequireSamesiteMatcher implements RequestMatcher {
    private static final Pattern ALLOWED_METHODS = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
    private static final Pattern API_PATTERN = Pattern.compile("^/api(?!/auth).*$");

    private static final String STRICT = "Strict";

    @Override
    public boolean matches(HttpServletRequest request) {
        String path = request.getRequestURI();
        if (ALLOWED_METHODS.matcher(request.getMethod()).matches() || API_PATTERN.matcher(path).matches()) {
            return false;
        }
        String samesite = request.getHeader("Cookie");
        return samesite != null && !containsToken(samesite, STRICT);
    }

    private boolean containsToken(String samesite, String token) {
        String[] tokens = samesite.split(";");
        for (String t : tokens) {
            if (t.trim().startsWith(token)) {
                return true;
            }
        }
        return false;
    }
}

以上即为Spring Security中防护CSRF的常见方法。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringSecurity跨域请求伪造(CSRF)的防护实现 - Python技术站

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

相关文章

  • SSM项目频繁打成war包部署,使用tomcat和maven实现热部署配置

    下面是SSM项目频繁打成war包部署并使用tomcat和maven实现热部署配置的完整攻略。 1. 前置条件 在开始之前,确保以下条件已满足: 项目使用maven进行构建 tomcat服务器已正确安装并运行 项目使用spring、spring mvc、mybatis等框架 2. 配置pom.xml文件 在项目的pom.xml文件中添加以下依赖: <de…

    Java 2023年5月19日
    00
  • 详解SpringMVC的类型转换及验证方法

    详解SpringMVC的类型转换及验证方法 SpringMVC是一个非常流行的Java Web框架,它提供了许多有用的功能,包括类型转换和验证。在本文中,我们将详细介绍SpringMVC的类型转换和验证方法,并提供一些示例来说明这些方法的使用。 类型转换 在SpringMVC中,我们可以使用类型转换器将请求参数转换为Java对象。SpringMVC提供了许多…

    Java 2023年5月17日
    00
  • IntelliJ IDEA中配置Tomcat超详细教程

    下面就介绍一下在 IntelliJ IDEA 中配置 Tomcat 并部署 Web 应用的详细步骤: 1. 下载并安装 Tomcat 首先,我们需要从 Apache Tomcat 的官网(https://tomcat.apache.org/)下载 Tomcat,下载完后按照说明安装即可。 2. 创建 Web 项目 在 IntelliJ IDEA 中创建一个新…

    Java 2023年6月3日
    00
  • Java8新特性之空指针异常的克星Optional类的实现

    Java8新特性之空指针异常的克星Optional类的实现 前言 在 Java 中,我们经常会遇到空指针异常(NullPointerException),尤其是在处理数据集合或者从接口返回数据时,如果拿到了 null 值,程序就会抛出异常。 Java 8 中提供了一个克星空指针异常的类 Optional,它可以有效地解决 null 值的问题。 Optiona…

    Java 2023年5月27日
    00
  • Spring Security常用过滤器实例解析

    接下来我将为您详细讲解 Spring Security 常用过滤器实例解析的完整攻略。 1. Spring Security 常用过滤器简介 Spring Security 是一种强大且高度可定制的认证和授权框架,它为 Web 应用程序提供了安全性。Spring Security 通过使用一系列过滤器来保护应用程序,并控制对资源的认证和授权访问。Spring…

    Java 2023年5月20日
    00
  • 详解使用Spring Data repository进行数据层的访问问题

    一、介绍Spring Data Repository Spring Data Repository是一种非常常用的用于访问数据层的组件。在Spring Data Repository中,只需要定义一个接口,并在接口中声明好需要的方法,就可以实现自动化的数据访问。具体而言,Spring Data会通过接口方法的名称和参数来推测query的内容,从而自动生成对应…

    Java 2023年5月20日
    00
  • Java中DataInputStream和DataOutputStream的使用方法

    下面就来详细讲解一下Java中DataInputStream和DataOutputStream的使用方法。 一、基本概述 DataInputStream和DataOutputStream是Java IO包中的两个类,分别用于基本数据类型的读写操作。DataInputStream提供了一系列方法来读取不同类型的基本数据类型,DataOutputStream提供…

    Java 2023年5月26日
    00
  • Java中启动线程start和run的两种方法

    启动线程是Java并发编程中的重要话题。在Java中,启动线程有两种方法,分别是调用Thread类的start()方法和直接调用run()方法。 为什么要使用线程 在Java中,线程的创建和启动可以让程序并发执行,实现多任务的处理。进程是由操作系统进行资源分配和调度的,而线程是在进程的基础上创建的,可以利用CPU时间片轮流获得执行时间。这样就可以让程序在一定…

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