栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Security - 13 禁用 CSRF、获取 CSRF 值

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Security - 13 禁用 CSRF、获取 CSRF 值

文章目录

环境项目结构在禁用 CSRF 防护的情况下,使用 POST 请求在启用 CSRF 防护的情况下,使用 POST 请求参考
Spring Security 默认启用 CSRF (Cross Site Request Forgery) 防护。如果你需要提交一个 POST 请求,那么,你需要在请求中携带 CSRF 值,或者禁用 CSRF 防护。

环境

操作系统:

Windows 10 x64

集成开发环境:

Spring Tool Suite 4 
Version: 4.14.0.RELEASE
Build Id: 202203131612

Postman(客户端):

Postman for Windows
Version 7.36.7
win32 10.0.19044 / x64
项目结构

参考:

    Spring Security - 11 允许匿名访问某些资源Spring Security - 12 模拟 JDBC 获取用户信息进行认证

在禁用 CSRF 防护的情况下,使用 POST 请求

假设在应用中存在一个用于用户注册的接口,如下(第 23 ~ 32 行):

package com.mk.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import lombok.extern.slf4j.Slf4j;

@Controller
@Slf4j
public class HelloController {

    // 其他...

    @PostMapping(path = "register")
    @ResponseBody
    public Map register(String username, String password) {
        Map map = new HashMap<>();
        
        map.put("username", username);
        map.put("password", password);
        
        return map;
    }
}

为了使匿名用户也能访问这个接口,我们需要在 WebSecurityConfigurer 配置类中做一些简单的配置,添加匿名访问的路径(第 21 ~ 24 行):

package com.mk.security.config.annotation.web.configuration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;

//@Configuration
@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {

    // 其他...
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin(); // Specifies to support form based authentication.
        
        http.authorizeRequests(customizer -> {
            String anonymous[] = { "/register" };
          
            // Specify that URLs are allowed by anyone.
            customizer.antMatchers(anonymous).permitAll();
          
            // Any request are allowed by any authenticated user.
            customizer.anyRequest().authenticated();
        });
    }
}

在没有禁用 CSRF 防护的情况下,使用 Postman 提交一个 POST 请求,我们将得到这样的返回信息:

这是因为 Spring Security 默认启用 CSRF 防护。如果你需要提交一个 POST 请求,那么,你需要在请求中携带 CSRF 值,或者禁用 CSRF 防护。

想要禁用 CSRF 防护,只需在 WebSecurityConfigurer 配置类的 configure(HttpSecurity) 方法中,添加如下配置即可(第 10 ~ 12 行):

@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {

    // 其他...
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 其他...
        
        http.csrf(customizer -> {
            customizer.disable();
        });
    }
}

重启应用之后,使用 Postman 提交一个 POST 请求,我们将得到预期的返回信息:

在启用 CSRF 防护的情况下,使用 POST 请求

在启用 CSRF 防护的情况下,使用 POST 请求,需要额外提交一个 CSRF 值。

想要获取 CSRF 值,只需在应用中添加一个控制器类,通过 Spring 注入 CsrfToken 参数,然后返回即可(第 19 ~ 22 行):

package com.mk.security.controller;

import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CsrfController {

    
    @GetMapping("/csrf")
    public CsrfToken csrf(CsrfToken token) {
        return token;
    }
}

此外,我们需要允许用户能够匿名访问这个接口,修改 WebSecurityConfigurer 配置类,添加允许匿名访问的路径(第 21 ~ 24 行):

package com.mk.security.config.annotation.web.configuration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;

//@Configuration
@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {

    // 其他...
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin(); // Specifies to support form based authentication.
        
        http.authorizeRequests(customizer -> {
            String anonymous[] = { "/csrf", "/register" };
          
            // Specify that URLs are allowed by anyone.
            customizer.antMatchers(anonymous).permitAll();
          
            // Any request are allowed by any authenticated user.
            customizer.anyRequest().authenticated();
        });
        
//        http.csrf(customizer -> {
//            customizer.disable();
//        });
    }
}

重启应用之后,使用 Postman 访问 http://127.0.0.1:8080/csrf 获取 CSRF 值:

记住 CSRF 值,然后在访问 http://127.0.0.1:8080/register 时,一起提交这个 CSRF 值,我们将得到预期的返回信息:

参考

Spring Security / Features / Protection Against Exploits / CSRF

Spring Security / Servlet Applications / Protection Against Exploits / Cross Site Request Forgery (CSRF) for Servlet Environments

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/781224.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号