0


【Spring Security】认证&密码加密&Token令牌&CSRF的使用详解

🎉🎉欢迎来到我的CSDN主页!🎉🎉

🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚

🌟推荐给大家我的专栏《Spring Security》。🎯🎯

👉点击这里,就可以查看我的主页啦!👇👇

Java方文山的个人主页

🎁如果感觉还不错的话请给我点赞吧!🎁🎁

💖期待你的加入,一起学习,一起进步!💖💖

请添加图片描述

前言

我们都知道Spring Security是做认证的,那它到底是怎么认证的呢?它是怎么将明文密码加密的呢?Token令牌的使用与CSRF跨域请求伪造是什么等等我们都不知道,但是通过这篇文章我相信你会有所了解有所收获!!!

一、基于Security认证

1.前期准备

基于

  1. Spring Initializr

创建

  1. SpringBoot

项目,实现与

  1. MyBatisPlus

的项目整合。分别导入:

  1. CodeGenerator

  1. MyBatisPlusConfig

  1. CodeGenerator

:用于

  1. MybatisPlus

代码生成;

  1. MyBatisPlusConfig

  1. MyBatisPlus

配置类,实现了分页和乐观锁相关配置。

1.1.添加pom.xml依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-freemarker</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-web</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>mysql</groupId>
  11. <artifactId>mysql-connector-java</artifactId>
  12. <scope>runtime</scope>
  13. <version>5.1.44</version>
  14. </dependency>
  15. <dependency>
  16. <groupId>org.projectlombok</groupId>
  17. <artifactId>lombok</artifactId>
  18. <optional>true</optional>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-test</artifactId>
  23. <scope>test</scope>
  24. </dependency>
  25. <dependency>
  26. <groupId>com.baomidou</groupId>
  27. <artifactId>mybatis-plus-boot-starter</artifactId>
  28. <version>3.5.2</version>
  29. </dependency>
  30. <dependency>
  31. <groupId>com.baomidou</groupId>
  32. <artifactId>mybatis-plus-generator</artifactId>
  33. <version>3.5.2</version>
  34. </dependency>
  35. <dependency>
  36. <groupId>com.alibaba</groupId>
  37. <artifactId>fastjson</artifactId>
  38. <version>2.0.32</version>
  39. </dependency>

1.2.配置application.yml

  1. spring:
  2. datasource:
  3. type: com.zaxxer.hikari.HikariDataSource
  4. driver-class-name: com.mysql.jdbc.Driver
  5. username: root
  6. password: 1234
  7. url: jdbc:mysql://localhost:3306/vue?useUnicode=true&characterEncoding=utf8&useSSL=false
  8. freemarker:
  9. enabled: true
  10. suffix: .ftl
  11. template-loader-path: classpath:/templates/
  12. mybatis-plus:
  13. # Mybatis Mapper所对应的XML位置
  14. mapper-locations: classpath:mapper/*.xml
  15. # 别名包扫描路径
  16. type-aliases-package: com.zking.spbootauthc.model
  17. # 是否开启自动驼峰命名规则(camel case)映射
  18. configuration:
  19. map-underscore-to-camel-case: true
  20. global-config:
  21. db-config:
  22. logic-delete-field: deleted # 全局逻辑删除的实体字段名
  23. logic-delete-value: 1 # 逻辑已删除值(默认为 1)
  24. logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
  25. logging:
  26. level:
  27. com.zking.spbootauthc.mapper: debug

修改数据库相关账号、密码及数据库名。

1.3.导入相关数据表

表名说明sys_user用户信息表sys_role角色信息表sys_module模块信息表(权限信息表)sys_user_role用户角色表sys_role_module角色模块表
表之间的关系说明:

数据表中有以上字段即可,后续我们还要加的。

1.4.实现MP代码生成

直接运行

  1. CodeGenerator.java

类,生成

  1. sys_

开头的相关信息表。

  1. package com.csdn.security.config;
  2. import com.baomidou.mybatisplus.generator.FastAutoGenerator;
  3. import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
  4. import com.baomidou.mybatisplus.generator.config.OutputFile;
  5. import com.baomidou.mybatisplus.generator.config.rules.DateType;
  6. import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
  7. import lombok.extern.slf4j.Slf4j;
  8. import java.util.Arrays;
  9. import java.util.Collections;
  10. import java.util.List;
  11. @Slf4j
  12. public class MySQLGenerator {
  13. private final static String URL = "jdbc:mysql://localhost:3306/goods?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC";
  14. private final static String USERNAME = "root";
  15. private final static String PASSWORD = "root789";
  16. private final static DataSourceConfig.Builder DATA_SOURCE_CONFIG =
  17. new DataSourceConfig.Builder(URL, USERNAME, PASSWORD);
  18. public static void main(String[] args) {
  19. FastAutoGenerator.create(DATA_SOURCE_CONFIG)
  20. .globalConfig(
  21. (scanner, builder) ->
  22. builder.author("Java方文山")
  23. .outputDir(System.getProperty("user.dir") + "\\src\\main\\java")
  24. .commentDate("yyyy-MM-dd")
  25. .dateType(DateType.TIME_PACK)
  26. )
  27. .packageConfig((builder) ->
  28. builder.parent("com.csdn.boot")
  29. .entity("pojo")
  30. .service("Service")
  31. .serviceImpl("Service.impl")
  32. .mapper("mapper")
  33. .xml("mapper.xml")
  34. .pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "\\src\\main\\resources\\mapper"))
  35. )
  36. .injectionConfig((builder) ->
  37. builder.beforeOutputFile(
  38. (a, b) -> log.warn("tableInfo: " + a.getEntityName())
  39. )
  40. )
  41. .strategyConfig((scanner, builder) ->
  42. builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all")))
  43. .addTablePrefix("tb_", "t_", "lay_", "meeting_", "sys_")
  44. .entityBuilder()
  45. .enableChainModel()
  46. .enableLombok()
  47. .enableTableFieldAnnotation()
  48. .controllerBuilder()
  49. .enableRestStyle()
  50. .enableHyphenStyle()
  51. .build()
  52. )
  53. .templateEngine(new FreemarkerTemplateEngine())
  54. .execute();
  55. }
  56. protected static List<String> getTables(String tables) {
  57. return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
  58. }
  59. }

1.5.为sys_user添加认证字段

前面说到有些字段需要后期加,至于是什么字段我事先没有给大家说的原因是想大家知道,为什么要加这些字段,这些字段是什么意思,首先在SecurityFilterChain过滤链编写重定向登录成功的首页方法

  1. //设置登录成功后重定向到那个页面
  2. .successHandler((req,resp,auth)->{
  3. resp.sendRedirect("/index");
  4. })

方便我们查看里面到底有什么参数

可以看到以上除了username\password都是我们没有的,我们接下来就把这些属性加上即可,因为这里Security必须要用到UserDetails这个类,所以我们自己的user类就就需要实现这个类。

  1. UserDetails

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

  1. UserDetails

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

以下是

  1. UserDetails

接口中定义的方法:

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

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

  1. UserDetails

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

我们直接定义这些属性即可,随后在数据库加上这些属性,注意默认值为1,否则认证不成功,因为除了0之外的数字都是真,如果为0就是假也就是false,那么我们认证的字段有一个为false必然是不成功的。

2.SpringSecurity之认证

2.1业务对象UserDetailsService

修改

  1. UserServiceImpl

并实现

  1. UserDetailsService

,重写

  1. loadUserByUsername(String username)

方法。

  1. @Service
  2. public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService, UserDetailsService {
  3. /**
  4. * 实现Spring Security内置的UserDetailService接口,重写loadUserByUsername方法实现数据库的身份校验
  5. * @param username
  6. * @return
  7. * @throws UsernameNotFoundException
  8. */
  9. @Override
  10. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  11. //根据用户名查询数据库中用户信息
  12. User user = this.getOne(new QueryWrapper<User>().eq("username", username));
  13. //判断用户是否存在
  14. if(Objects.isNull(user))
  15. throw new UsernameNotFoundException("用户不存在");
  16. //权限校验TODO,后续讲解
  17. return user;
  18. }
  19. }

**

  1. UserDetailsService

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

  1. loadUserByUsername

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

  1. UserDetails

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

  1. UserDetailsService

通常与

  1. DaoAuthenticationProvider

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

2.2.SecurityConfig配置

创建**

  1. WebSecurityConfig

配置类,配置

  1. SpringSecurity

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

  1. package com.csdn.security.config;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.security.authentication.AuthenticationManager;
  6. import org.springframework.security.authentication.ProviderManager;
  7. import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
  8. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  9. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  10. import org.springframework.security.core.userdetails.UserDetailsService;
  11. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  12. import org.springframework.security.crypto.password.NoOpPasswordEncoder;
  13. import org.springframework.security.crypto.password.PasswordEncoder;
  14. import org.springframework.security.web.SecurityFilterChain;
  15. @Configuration
  16. //开启SpringSecurity的默认行为
  17. @EnableWebSecurity
  18. public class WebSecurityConfig {
  19. /**
  20. * 配置密码编码器,首次采用明文密码方式进行比对校验
  21. */
  22. @Bean
  23. public PasswordEncoder passwordEncoder(){
  24. return new BCryptPasswordEncoder();
  25. }
  26. /**
  27. * 基于数据库方式进行身份认证和权限鉴定
  28. */
  29. @Autowired
  30. private UserDetailsService userDetailsService;
  31. /**
  32. * 获取AuthenticationManager(认证管理器),登录时认证使用(基于数据库方式)
  33. * @param
  34. * @return
  35. * @throws Exception
  36. */
  37. @Bean
  38. public AuthenticationManager authenticationManager() throws Exception {
  39. //创建DaoAuthenticationProvider
  40. DaoAuthenticationProvider provider=new DaoAuthenticationProvider();
  41. //设置userDetailsService,基于数据库方式进行身份认证
  42. provider.setUserDetailsService(userDetailsService);
  43. //配置密码编码器
  44. provider.setPasswordEncoder(passwordEncoder());
  45. return new ProviderManager(provider);
  46. }
  47. @Bean
  48. public SecurityFilterChain securityFilterChain(HttpSecurity http)
  49. throws Exception {
  50. http.authorizeRequests()
  51. // 开放接口访问权限,不需要登录就可以访问
  52. .antMatchers("/toLogin").permitAll()
  53. // 设置角色权限
  54. .antMatchers("/admin/**").hasRole("ADMIN")
  55. .antMatchers("/user/**").hasAnyRole("ADMIN", "USER")
  56. // 其余所有请求全部需要鉴权认证
  57. .anyRequest().authenticated()
  58. .and()
  59. .formLogin()
  60. // 设置登录页面的 URL
  61. .loginPage("/toLogin")
  62. // 设置登录请求的 URL,即表单提交的 URL
  63. .loginProcessingUrl("/userLogin")
  64. // 设置登录表单中用户名字段的参数名,默认为username
  65. .usernameParameter("username")
  66. // 设置登录表单中密码字段的参数名,默认为password
  67. .passwordParameter("password")
  68. //设置登录成功后重定向到那个页面
  69. .successHandler((req,resp,auth)->{
  70. resp.sendRedirect("/index");
  71. })
  72. .and()
  73. .logout()
  74. // 设置安全退出的URL路径
  75. .logoutUrl("/logout")
  76. // 设置退出成功后跳转的路径
  77. .logoutSuccessUrl("/")
  78. ;
  79. //跳转登录页重新登录问题:用于禁用 CSRF(Cross-Site Request Forgery)防护机制。
  80. http.csrf().disable();
  81. //定义访问被拒绝时的处理方式,会重定向到noauth(也就是没有权限的页面展示)
  82. http.exceptionHandling().accessDeniedPage("/noauth");
  83. return http.build();
  84. }
  85. }

至此就可以完成了通过数据库的用户进行认证登录操作了,这里需要注意的是**

  1. formLogin

**认证失败后将不在使用

  1. **failureForwardUrl**()

方法转发,而是使用**

  1. failureHandler

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

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

二、密码加密

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

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

1.自定义MD5加密

创建自定义

  1. MD5

加密类并实现**

  1. PasswordEncoder

**:

  1. public class CustomMd5PasswordEncoder implements PasswordEncoder {
  2. @Override
  3. public String encode(CharSequence rawPassword) {
  4. //对密码进行 md5 加密
  5. String md5Password = DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes());
  6. System.out.println(md5Password);
  7. return md5Password;
  8. }
  9. @Override
  10. public boolean matches(CharSequence rawPassword, String encodedPassword) {
  11. // 通过md5校验
  12. System.out.println(rawPassword);
  13. System.out.println(encodedPassword);
  14. return encode(rawPassword).equals(encodedPassword);
  15. }
  16. }

修改**

  1. SecurityConfig

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

  1. @Bean
  2. public PasswordEncoder passwordEncoder(){
  3. // 自定义MD5加密方式:
  4. return new CustomMd5PasswordEncoder();
  5. }

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

  1. MD5

加密密码:

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

最后,将生成的

  1. MD5

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

2.BCryptPasswordEncoder密码编码器

**

  1. BCryptPasswordEncoder

  1. Spring Security

中一种基于

  1. bcrypt

算法的密码加密方式。

  1. bcrypt

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

使用**

  1. BCryptPasswordEncoder

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

  1. salt

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

  1. salt

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

在**

  1. Spring Security

中,可以通过在

  1. SecurityConfig

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

  1. BCryptPasswordEncoder

**进行密码加密:

  1. @Bean
  2. public PasswordEncoder passwordEncoder() {
  3. return new BCryptPasswordEncoder();
  4. }

这样就可以在Spring Security中使用**

  1. BCryptPasswordEncoder

**进行密码加密了,细心的同志在刚刚认证的时候应该就发现了。

3.BCrypt工作原理

BCrypt是一种单向哈希函数,它使用salt(盐)和cost(成本因子)来增加哈希的安全性。

下面是BCryptPasswordEncoder的工作原理:

  1. 加密过程:- 生成一个随机的盐值。- 使用盐值和密码作为输入,通过BCrypt算法进行哈希计算。- 将盐值和计算得到的哈希值拼接在一起,并返回最终的加密结果。

这里假如有两个密码都为123但是salt不一样,可能是18293也可能是18392,但是他们的密码都是123,只是将原本的密码加上了“盐”后再进行哈希算法得到了一个值。

  1. 验证过程:- 从存储中获取已加密的密码和对应的盐值。- 使用输入的密码和盐值,通过BCrypt算法进行哈希计算。- 将计算得到的哈希值与存储中的密码进行比较,如果匹配则验证成功,否则验证失败。

三、基于BCrypt完成Token

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

  1. Remember-Me

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

  1. Token

** 并保存在用户浏览器的 **

  1. Cookie

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

**

  1. Spring Security

**提供了两种 **

  1. Remember-Me

** 的实现方式:

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

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

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

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

  1. SpringSecurity

自动生成。

  • 基于持久化Token配置,修改**SecurityConfig**配置类:

**

  1. Remember-Me

** 功能的开启需要在**

  1. configure(HttpSecurity http)

方法中通过

  1. http.rememberMe()

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

  1. RememberMeAuthenticationFilter

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

  1. @Resource
  2. public DataSource dataSource;
  3. /**
  4. * 配置持久化Token方式,注意tokenRepository.setCreateTableOnStartup()配置
  5. */
  6. @Bean
  7. public PersistentTokenRepository persistentTokenRepository(){
  8. JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
  9. tokenRepository.setDataSource(dataSource);
  10. // 设置为true要保障数据库该表不存在,不然会报异常哦
  11. // 所以第二次打开服务器应用程序的时候得把它设为false
  12. tokenRepository.setCreateTableOnStartup(false);
  13. return tokenRepository;
  14. }

** 在SecurityFilterChain中添加规则**

  1. .and()
  2. .rememberMe()
  3. // 指定 rememberMe 的参数名,用于在表单中携带 rememberMe 的值。
  4. //.rememberMeParameter("remember-me")
  5. // 指定 rememberMe 的有效期,单位为秒,默认2周。
  6. .tokenValiditySeconds(30)
  7. // 指定 rememberMe 的 cookie 名称。
  8. .rememberMeCookieName("remember-me-cookie")
  9. // 指定 rememberMe 的 token 存储方式,可以使用默认的 PersistentTokenRepository 或自定义的实现。
  10. .tokenRepository(persistentTokenRepository())
  11. // 指定 rememberMe 的认证方式,需要实现 UserDetailsService 接口,并在其中查询用户信息。
  12. .userDetailsService(userDetailsService)
  1. rememberMe

主要方法介绍:
方法说明

  1. rememberMeParameter()

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

  1. HTTP

参数,默认为

  1. remember-me
  1. tokenValiditySeconds()

设置

  1. Token

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

  1. tokenRepository()

指定

  1. rememberMe

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

  1. PersistentTokenRepository

或自定义的实现

  1. userDetailsService()

指定

  1. UserDetailsService

对象

  1. rememberMeCookieName()

指定

  1. rememberMe

  1. cookie

名称

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

注意:配置的

  1. checkbox

复选框的

  1. name

属性名要与上面配置的

  1. rememberMeParameter("属性名")

一致,默认就叫

  1. remember-me

总结:

  1. remember-me

只有在

  1. JSESSIONID

失效和

  1. SecurityContextPersistenceFilter

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

  1. remember-me

  1. Cookie

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

  1. remember-me

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

  1. Token

替换旧的

  1. Token

,相应

  1. Cookie

  1. Max-Age

也会重置。

下图是我们没有加Token令牌如果反复刷新会要我们重新提交表单

加了Token之后并且勾选复选框记住我将Token保存到cookie中

数据表中也会有数据

四、CSRF跨域伪请求

在**

  1. Spring Security

中,防范

  1. CSRF

攻击可以通过启用

  1. CSRF

保护来实现。启用

  1. CSRF

保护后,

  1. Spring Security

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

  1. CSRF Token

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

  1. Token

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

  1. CSRF

保护的方式是在

  1. Spring Security

**配置文件中添加

  1. .csrf()

方法,例如:

  1. http
  2. .csrf()
  3. .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());

将原来的关闭CSRF注释掉换成我们的

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

  1. CookieCsrfTokenRepository

作为

  1. CSRF Token

的存储方式,并设置了

  1. httpOnly

  1. false

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

  1. Token

  1. .csrf()

主要方法介绍:
方法说明

  1. disable()

关闭

  1. CSRF

防御

  1. csrfTokenRepository()

设置

  1. CookieCsrfTokenRepository

实例,用于存储和检索

  1. CSRF

令牌。与

  1. HttpSessionCsrfTokenRepository

不同,

  1. CookieCsrfTokenRepository

  1. CSRF

令牌存储在

  1. cookie

中,而不是在会话中。

  1. ignoringAntMatchers()

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

  1. CSRF

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

  1. /api/

开头的请求,可以使用

  1. .ignoringAntMatchers("/api/**")

  1. csrfTokenManager()

设置

  1. CsrfTokenManager

实例,用于管理

  1. CSRF

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

  1. Spring Security

使用

  1. DefaultCsrfTokenManager

实例来生成和验证

  1. CSRF

令牌。

  1. requireCsrfProtectionMatcher()

设置

  1. RequestMatcher

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

  1. CSRF

保护。默认情况下,

  1. Spring Security

将对所有非

  1. GETHEADOPTIONSTRACE

请求进行

  1. CSRF

保护。
使用了

  1. spring-security

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

  1. POST

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

  1. _csrf

参数,一旦传来的

  1. _csrf

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

**修改

  1. login.ftl

页面代码,加入

  1. _csrf

隐藏域。**

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

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

  1. CSRF

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

  1. http.csrf().ignoringAntMatchers("/upload"); // 禁用/upload接口的CSRF防御

请添加图片描述

到这里我的分享就结束了,欢迎到评论区探讨交流!!

💖如果觉得有用的话还请点个赞吧 💖


本文转载自: https://blog.csdn.net/weixin_74318097/article/details/135135288
版权归原作者 Java方文山 所有, 如有侵权,请联系我们删除。

“【Spring Security】认证&密码加密&Token令牌&CSRF的使用详解”的评论:

还没有评论