0


【Spring Security】认证之案例的使用、MD5加密、CSRF防御

一、引言

1、什么是SpringSecurity认证

    Spring Security认证是指基于Spring Security框架的身份验证过程。身份验证是指验证某个用户是否为系统中的合法主体,即用户能否访问该系统。在Spring Security中,通常要求用户提供用户名和密码进行认证。系统通过校验用户名和密码来完成认证过程。如果用户通过了身份验证,他们就可以访问受保护的资源。Spring Security支持多种身份认证模式,例如基于表单的身份认证、OpenID身份认证、Jasig中央认证服务等。

2、为什么使用SpringSecurity之认证

  1. 安全性:Spring Security是一个成熟的安全框架,提供了许多安全特性,如身份验证、授权、密码加密等。它可以有效地保护应用程序的安全,防止各种常见的安全威胁和漏洞。
  2. 易于集成:Spring Security与Spring框架深度集成,可以方便地与Spring的其他功能配合使用,如依赖注入、事务管理等。这使得在Spring环境下开发安全功能更加便捷。
  3. 灵活性:Spring Security提供了丰富的配置选项和扩展点,可以根据具体需求进行灵活的定制。开发者可以根据应用程序的具体需求进行调整和优化。
  4. 社区支持:Spring Security拥有庞大的用户基础和活跃的社区,可以提供丰富的支持和资源。在遇到问题时,可以快速找到解决方案或寻求帮助。
  5. 文档完善:Spring Security的官方文档非常完善,提供了详细的说明和示例,可以帮助开发者快速上手并实现安全功能。

3、实现步骤

  1. 配置数据源:提供用于存储用户名和密码的数据源,例如数据库或LDAP服务器。
  2. 配置认证模块:配置身份验证模块以从数据源读取用户名和密码,并验证它们是否匹配。
  3. 配置授权模块:配置授权模块以确定用户是否有权访问特定的资源。这通常基于角色或权限。
  4. 配置安全配置类:通过创建一个实现SecurityFilterChain接口的类,配置Spring Security的过滤器链。在这个类中,可以定义哪些URL需要身份验证和授权,以及如何处理安全相关的异常。
  5. 配置视图解析器:配置视图解析器以将URL映射到相应的视图。在Spring Security中,可以使用Thymeleaf或JSP等模板引擎来创建视图。

二、快速实现(案例)

1、添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
    <version>5.1.44</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.2</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.2</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>2.0.32</version>
</dependency>
        <!--        security-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2、配置

配置application.yml

server:
  port: 8080
spring:
  datasource:
    username: root
    password: 1234
    url: jdbc:mysql://localhost:3306/vue?useUnicode=true&characterEncoding=utf8&useSSL=false
    driver-class-name: com.mysql.jdbc.Driver
  freemarker:
    enabled: true
    suffix: .ftl
    template-loader-path: classpath:/templates/
mybatis-plus:
  # Mybatis Mapper所对应的XML位置
  mapper-locations: classpath:mapper/*.xml
  # 别名包扫描路径
  type-aliases-package: com.wfzldr.springsecurity01.model
  # 是否开启自动驼峰命名规则(camel case)映射
  configuration:
    map-underscore-to-camel-case: true
  global-config:
    db-config:
      logic-delete-field: deleted # 全局逻辑删除的实体字段名
      logic-delete-value: 1       # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0   # 逻辑未删除值(默认为 0)
logging:
  level:
    com.wfzldr.springsecurity01.mapper: debug

3、导入数据表及相关代码

表名说明sys_user用户信息表sys_role角色信息表sys_module模块信息表(权限信息表)sys_user_role用户角色表sys_role_module角色模块表
sys_module

sys_role

sys_role_module

sys_user

sys_user_role

表之间的关系说明:

生成对应表的代码层

4、创建登录页及首页

基于

freemarker

模板引擎创建登录页

login.ftl

和首页

index.ftl

login.ftl

首页部分代码如下:

<h1>用户登录</h1>
<form action="/user/userLogin" method="post">
    <label>账号:</label><input type="text" name="username"/><br/>
    <label>密码:</label><input type="password" name="password"/><br/>
    <input type="submit" value="登 录"/>
</form>
index.ftl

代码如下:

<h1>首页</h1>
<div style="position: absolute;top:15px;right:15px;"><a href="/logout">安全退出</a></div>
href="/logout"

SpringSecurity

配置的退出请求路径。主要完成以下几个操作:

  1. 清除指定 CookieCookieClearingLogoutHandler#logout
  2. 清除 remember-mePersistentTokenBasedRememberMeServices#logout
  3. 使当前 Session无效,清空当前的 SecurityContext 中认证用户信息 Authentication

5、创建配置Controller

创建

IndexController

配置跳转首页和登录页的接口。

@Controller
public class IndexController {
​
    @RequestMapping("/")
    public String toLogin(){
        return "login";
    }
​
    @RequestMapping("/index")
    public String toIndex(){
        return "index";
    }
}

UserController

中配置请求登录接口:

@RestController
@RequestMapping("/user")
public class UserController {
​
    @RequestMapping("/userLogin")
    public String userLogin(User user){
        return "login";
    }
    
}

6、用户认证

6.1、用户对象UserDetails

修改

User

并实现

UserDetails

@Getter
@Setter
@TableName("sys_user")
public class User implements Serializable, UserDetails {
    ...
​
    /**
     * 用户权限集合
     * @return
     */
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }
​
    /**
     * 用户没过期返回true,反之则false
     */
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    /**
     * 用户没锁定返回true,反之则false
     */
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    /**
     * 用户凭据(通常为密码)没过期返回true,反之则false
     */
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    /**
     * 用户是启用状态返回true,反之则false
     */
    @Override
    public boolean isEnabled() {
        return true;
    }
}
   UserDetails

是Spring Security框架中的一个接口,它代表了应用程序中的用户信息。

UserDetails

接口定义了一组方法,用于获取用户的用户名、密码、角色和权限等信息,以便Spring Security可以使用这些信息进行身份验证和授权。

以下是

UserDetails

接口中定义的方法:

  • **getUsername()**:获取用户的用户名。
  • **getPassword()**:获取用户的密码。
  • **getAuthorities()**:获取用户的角色和权限信息。
  • **isEnabled()**:判断用户是否可用。
  • **isAccountNonExpired()**:判断用户的账号是否过期。
  • **isAccountNonLocked()**:判断用户的账号是否被锁定。
  • **isCredentialsNonExpired()**:判断用户的凭证是否过期。

自定义用户信息时,可以实现

UserDetails

接口并覆盖其中的方法来提供自己的用户信息。

6.2、业务对象UserDetailsService

修改

UserServiceImpl

并实现

UserDetailsService

,重写

loadUserByUsername(String username)

方法。

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
            implements UserService,UserDetailsService {
​
    /**
     * 实现Spring Security内置的UserDetailService接口,重写loadUserByUsername方法实现数据库的身份校验
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根据用户名查询数据库中用户信息
        User user = this.getOne(new QueryWrapper<User>().eq("username", username));
        //判断用户是否存在
        if(Objects.isNull(user))
            throw new UsernameNotFoundException("用户不存在");
        //权限校验TODO,后续讲解
        return user;
    }
}
UserDetailsService

是Spring Security中的一个接口,它用于从特定数据源(如数据库)中获取用户详细信息,以进行身份验证和授权。实现该接口的类需要实现

loadUserByUsername

方法,该方法根据给定的用户名返回一个

UserDetails

对象,该对象包含有关用户的详细信息,例如密码、角色和权限等。在Spring Security中,

UserDetailsService

通常与

DaoAuthenticationProvider

一起使用,后者是一个身份验证提供程序,用于验证用户的凭据。

6.3、SecurityConfig配置

创建

WebSecurityConfig

配置类,配置

SpringSecurity

结合数据库方式进行身份认证和权限鉴定。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
​
    /**
     * 基于数据库方式进行身份认证和权限鉴定
     */
    @Autowired
    private UserDetailsService userDetailsService;
    
    /**
     * 配置密码编码器,首次采用明文密码方式进行比对校验
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }
    
     /**
     * 获取AuthenticationManager(认证管理器),登录时认证使用(基于数据库方式)
     * @param
     * @return
     * @throws Exception
     */
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        //创建DaoAuthenticationProvider
        DaoAuthenticationProvider provider=new DaoAuthenticationProvider();
        //设置userDetailsService,基于数据库方式进行身份认证
        provider.setUserDetailsService(userDetailsService);
        //配置密码编码器
        provider.setPasswordEncoder(passwordEncoder());
        return new ProviderManager(provider);
    }
    
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
​
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .anyRequest().authenticated()
            .and()
                .formLogin()
                .loginPage("/")
                .loginProcessingUrl("/user/userLogin")
                .passwordParameter("password")
                .usernameParameter("username")
                // 认证成功 redirect跳转,根据上一保存请求进行成功跳转
                .defaultSuccessUrl("/index")
                // 认证成功 forward跳转,始终在认证成功之后跳转到指定请求
//                .successForwardUrl("/index")
//                .failureForwardUrl("/")
               /* .successHandler((request, response, exception)->{
                    response.sendRedirect("/index");
                })*/
                .failureHandler((request, response, exception) -> {
                    request.setAttribute("msg",exception.getMessage());
                    request.getRequestDispatcher("/").forward(request,response);
                })
            .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/")
            .and()
                .csrf().disable()
                ;
        return http.build();
    }
}

这里需要注意的是

formLogin

认证失败后将不在使用

failureForwardUrl()

方法转发,而是使用

failureHandler

处理器方式处理错误信息并跳转页面。

  • 如果使用failureForwardUrl()方式,请到ForwardAuthenticationFailureHandler源码中查看错误信息封装:

SpringSecurity

将认证错误信息保存到

Request

作用域中,并取名为

SPRING_SECURITY_LAST_EXCEPTION

,所以直接可以到前端页面使用

${SPRING_SECURITY_LAST_EXCEPTION}

方式进行获取展示。

  • 如果使用failureHandler处理器方式,则可以自定义错误页面及错误信息:
.failureHandler((request, response, exception) -> {
    //将认证错误信息保存到request作用域,取名为msg
    request.setAttribute("msg",exception.getMessage());
    //认证失败后转发到指定页面
    request.getRequestDispatcher("/").forward(request,response);
})

本次案例使用的是自定义

failureHandler

处理器方式,修改登录页面

login.ftl

加入错误信息展示区域:

<div>${msg!}</div>

7、启动测试

在sys_user表中添加测试用户信息,此处请使用明文密码方式进行身份验证。

修改

IndexController

中的跳转到首页的方法,加入获取

SpringSecurity

认证信息并带入前段页面进行展示。

@RequestMapping("/index")
public String toIndex(Model model){
    //获取Spring Security认证成功后的相关信息
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    //将认证信息转换成JSON数据
    String json = JSON.toJSONString(authentication);
    //存入数据模型中带入前端页面进行展示
    model.addAttribute("auth",json);
    return "index";
}

启动项目并进行登录测试。

index.ftl

首页中通过

${auth}

展示

SpringSecurity

认证成功的相关信息。

三、密码方式

Spring Security提供了多种密码加密方式,大致可以归类于以下几种:

  • 对密码进行明文处理,即不采用任何加密方式;
  • 采用MD5加密方式;
  • 采用哈希算法加密方式;

1、自定义MD5加密

创建自定义

MD5

加密类并实现

PasswordEncoder

public class CustomMd5PasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence rawPassword) {
        //对密码进行 md5 加密
        String md5Password = DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes());
        System.out.println(md5Password);
        return md5Password;
    }

    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        // 通过md5校验
        System.out.println(rawPassword);
        System.out.println(encodedPassword);
        return encode(rawPassword).equals(encodedPassword);
    }
}

修改

SecurityConfig

配置类,更换密码编码器:

@Bean
public PasswordEncoder passwordEncoder(){
    // 自定义MD5加密方式:
    return new CustomMd5PasswordEncoder();
}

数据库中的用户密码也需要更换成对应自定义

MD5

加密密码:

//MD5自定义加密方式:
String pwd =  DigestUtils.md5DigestAsHex("123456".getBytes());
System.out.println(pwd);

最后,将生成的

MD5

加密密码保存到数据库表中。

2、BCryptPasswordEncoder密码编码器

  BCryptPasswordEncoder

Spring Security

中一种基于

bcrypt

算法的密码加密方式。

bcrypt

算法是一种密码哈希函数,具有防止彩虹表攻击的优点,因此安全性较高。

    使用
BCryptPasswordEncoder

进行密码加密时,可以指定一个随机生成的

salt

值,将其与原始密码一起进行哈希计算。salt值可以增加密码的安全性,因为即使两个用户使用相同的密码,由于使用不同的

salt

值进行哈希计算,得到的哈希值也是不同的。

Spring Security

中,可以通过在

SecurityConfig

配置类中添加以下代码来使用

BCryptPasswordEncoder

进行密码加密:

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

这样就可以在Spring Security中使用

BCryptPasswordEncoder

进行密码加密了。

四、RememberMe

    在实际开发中,为了用户登录方便常常会启用记住我(
Remember-Me

)功能。如果用户登录时勾选了“记住我”选项,那么在一段有效时间内,会默认自动登录,免去再次输入用户名、密码等登录操作。该功能的实现机理是根据用户登录信息生成

Token

并保存在用户浏览器的

Cookie

中,当用户需要再次登录时,自动实现校验并建立登录态的一种机制。

Spring Security

提供了两种

Remember-Me

的实现方式:

  • 简单加密 Token:用散列算法加密用户必要的登录系信息并生成 Token 令牌。
  • 持久化 Token:数据库等持久性数据存储机制用的持久化 Token 令牌。

基于持久化Token配置步骤如下:

  • 创建数据库表 persistent_logins,用于存储自动登录信息
CREATE TABLE `persistent_logins` (
  `username` varchar(64) NOT NULL,
  `series` varchar(64) PRIMARY KEY,
  `token` varchar(64) NOT NULL,
  `last_used` timestamp NOT NULL
);

该步骤可以不做,在后续的配置过程中可以交由

SpringSecurity

自动生成。

  • 基于持久化Token配置,修改SecurityConfig配置类:
Remember-Me

功能的开启需要在

configure(HttpSecurity http)

方法中通过

http.rememberMe()

配置,该配置主要会在过滤器链中添加

RememberMeAuthenticationFilter

过滤器,通过该过滤器实现自动登录。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
​
    //省略其他配置,参考之前
    
    @Autowired
    public UserDetailsService userDetailsService;
    
    @Resource
    public DataSource dataSource;
    
    /**
     * 配置持久化Token方式,注意tokenRepository.setCreateTableOnStartup()配置
     */
    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        // 设置为true要保障数据库该表不存在,不然会报异常哦
        // 所以第二次打开服务器应用程序的时候得把它设为false
        tokenRepository.setCreateTableOnStartup(false);
        return tokenRepository;
    }
    
     @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
​
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .anyRequest().authenticated()
            .and()
                .formLogin()
                .loginPage("/")
                .loginProcessingUrl("/user/userLogin")
                .passwordParameter("password")
                .usernameParameter("username")
                // 认证成功 redirect跳转,根据上一保存请求进行成功跳转
                .defaultSuccessUrl("/index")
                // 认证成功 forward跳转,始终在认证成功之后跳转到指定请求
                //.successForwardUrl("/index")
                //failureForwardUrl("/")
                /*.successHandler((request, response, exception)->{
                    response.sendRedirect("/index");
                })*/
                .failureHandler((request, response, exception) -> {
                    request.setAttribute("msg",exception.getMessage());
                    request.getRequestDispatcher("/").forward(request,response);
                })
            .and()
                .rememberMe()
                // 指定 rememberMe 的参数名,用于在表单中携带 rememberMe 的值。
                //.rememberMeParameter("remember-me")
                // 指定 rememberMe 的有效期,单位为秒,默认2周。
                .tokenValiditySeconds(30)
                // 指定 rememberMe 的 cookie 名称。
                .rememberMeCookieName("remember-me-cookie")
                // 指定 rememberMe 的 token 存储方式,可以使用默认的 PersistentTokenRepository 或自定义的实现。
                .tokenRepository(persistentTokenRepository())
                // 指定 rememberMe 的认证方式,需要实现 UserDetailsService 接口,并在其中查询用户信息。
                .userDetailsService(userDetailsService)
            .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/")
            .and()
                .csrf().disable()
                ;
        return http.build();
    }
}
rememberMe

主要方法介绍:
方法说明

rememberMeParameter()

指定在登录时“记住我”的

HTTP

参数,默认为

remember-me
tokenValiditySeconds()

设置

Token

有效期为 200s,默认时长为 2 星期

tokenRepository()

指定

rememberMe

的 token 存储方式,可以使用默认的

PersistentTokenRepository

或自定义的实现

userDetailsService()

指定

UserDetailsService

对象

rememberMeCookieName()

指定

rememberMe

cookie

名称

  • 修改登录页面login.ftl,添加remember-Me记住我的checkbox选项框。
<form action="/user/userLogin" method="post">
    <label>账号:</label><input type="text" name="username"/><br/>
    <label>密码:</label><input type="password" name="password"/><br/>
    <input type="checkbox" name="remember-me"/>记住我<br/>
    <input type="submit" value="登 录"/>
</form>

注意:配置的

checkbox

复选框的

name

属性名要与上面配置的

rememberMeParameter("属性名")

一致,默认就叫

remember-me

总结:

remember-me

只有在

JSESSIONID

失效和

SecurityContextPersistenceFilter

过滤器认证失败或者未进行认证时才发挥作用。此时,只要

remember-me

Cookie

不过期,我们就不需要填写登录表单,就能实现再次登录,并且

remember-me

自动登录成功之后,会生成新的

Token

替换旧的

Token

,相应

Cookie

Max-Age

也会重置。

五、CSRF防御

1、什么是CSRF

  **CSRF**

**(

Cross-Site Request Forgery

**,跨站请求伪造)是一种利用用户已登录的身份在用户不知情的情况下发送恶意请求的攻击方式。攻击者可以通过构造恶意链接或者伪造表单提交等方式,让用户在不知情的情况下执行某些操作,例如修改密码、转账、发表评论等。

    为了防范
CSRF

攻击,常见的做法是在请求中添加一个

CSRF Token

(也叫做同步令牌、防伪标志),并在服务器端进行验证。

CSRF Token

是一个随机生成的字符串,每次请求都会随着请求一起发送到服务器端,服务器端会对这个

Token

进行验证,如果

Token

不正确,则拒绝执行请求。

2、SpringSecurity中如何使用CSRF

Spring Security

中,防范

CSRF

攻击可以通过启用

CSRF

保护来实现。启用

CSRF

保护后,

Spring Security

会自动在每个表单中添加一个隐藏的

CSRF Token

字段,并在服务器端进行验证。如果

Token

验证失败,则会抛出异常,从而拒绝执行请求。启用

CSRF

保护的方式是在

Spring Security

配置文件中添加

.csrf()

方法,例如:

http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());

在上面的配置中,我们使用了

CookieCsrfTokenRepository

作为

CSRF Token

的存储方式,并设置了

httpOnly

false

,以便在客户端可以访问到该

Token

.csrf()

主要方法介绍:
方法说明

disable()

关闭

CSRF

防御

csrfTokenRepository()

设置

CookieCsrfTokenRepository

实例,用于存储和检索

CSRF

令牌。与

HttpSessionCsrfTokenRepository

不同,

CookieCsrfTokenRepository

CSRF

令牌存储在

cookie

中,而不是在会话中。

ignoringAntMatchers()

设置一组Ant模式,用于忽略某些请求的

CSRF

保护。例如,如果您想要忽略所有以

/api/

开头的请求,可以使用

.ignoringAntMatchers("/api/**")

csrfTokenManager()

设置

CsrfTokenManager

实例,用于管理

CSRF

令牌的生成和验证。默认情况下,

Spring Security

使用

DefaultCsrfTokenManager

实例来生成和验证

CSRF

令牌。

requireCsrfProtectionMatcher()

设置

RequestMatcher

实例,用于确定哪些请求需要进行

CSRF

保护。默认情况下,

Spring Security

将对所有非

GET、HEAD、OPTIONS和TRACE

请求进行

CSRF

保护。
重启项目进行测试。

  • 问题一:开启了SpringSecurityCSRF防御之后导致登录的POST请求失败?

原因分析:使用了

spring-security

后,默认开启了防止跨域攻击的功能,任何

POST

提交到后台的表单都要验证是否带有

_csrf

参数,一旦传来的

_csrf

参数不正确,服务器便返回 403 错误。

解决方案:修改

login.ftl

页面代码,加入

_csrf

隐藏域。

<form action="/user/userLogin" method="post">
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
    <label>账号:</label><input type="text" name="username"/><br/>
    <label>密码:</label><input type="password" name="password"/><br/>
    <input type="checkbox" name="remember-me"/>记住我<br/>
    <input type="submit" value="登 录"/>
</form>

如果针对一些特定的请求接口,不需要进行

CSRF

防御,可以通过以下配置忽略:

http.csrf().ignoringAntMatchers("/upload"); // 禁用/upload接口的CSRF防御
  • 问题二:SpringSecurity退出登录/logout提示404问题

退出登录logout实现方式:

http.logout().logoutUrl("/logout").
                logoutSuccessUrl("/").permitAll();

结果运行项目,执行安全退出时提示页面404错误。

错误原因:

SpringSecurity3.2

开始,默认会启动

CSRF

防护,一旦启动了

CSRF

防护,

“/logout”

需要用post的方式提交,

SpringSecurity

才能过滤。

  • 方式一:配置文件直接关闭CSRF防护
http.csrf().disable();  //关闭csrf防护

注意:当关闭

CSRF

防护时,部分的页面可能会无法刷新,甚至报错。这时可以在页面的

标签之间加入以下代码:

<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>
  • 方式二:官方建议使用POST请求退出登陆,并携带CRSF令牌
http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).
                logoutSuccessUrl("/").permitAll();

分享就到这里!欢迎大家评论区讨论!

标签: spring java 前端

本文转载自: https://blog.csdn.net/weixin_74383330/article/details/135263725
版权归原作者 无法自律的人 所有, 如有侵权,请联系我们删除。

“【Spring Security】认证之案例的使用、MD5加密、CSRF防御”的评论:

还没有评论