目录
零、Spring Security 简介
一、创建一个Maven项目
1.1.添加启动器
1.2 编写配置文件
1.2.1 创建配置文件
1.2.2 编写配置文件
1.3 准备控制器
1.4 编写启动类
1.5 准备展示页面
1.6 运行程序( SpringBootMain )
二、了解 Spring Security 认证的逻辑:
2.1.了解页面逻辑
2.2.了解认证逻辑
2.3.0 建表,编写实体类,数据访问层(mapper)
2.3. 了解UserDetailsService接口逻辑:
2.3.1 创建一个业务层实现类 EmpServiceImpl,实现 UserDetailsService 接口
2.3.2 在 EmpServiceImpl 重写 loadUserByUsername 方法
2.3.2-1 分析UserDetailsService接口中方法的返回值:
2.3.3 编写测试类 DemoTest
2.3.3-1 报错:
2.3.3-2 PasswordEncoder 接口
2.3.3-3 了解SpringSecurity 的加密算法 ==> 密码解析器:
2.3.4 运行 test1
三、自定义登录页面
3.1 编写登录页面( empLogin.html )
3.2 修改控制类( EmpController )
3.3 编写自定义配置类 MyConfig
3.4 自定义登录成功和失败页面
3.5 编写登录成功后跳转的页面( success.html )
3.6 运行 SpringBootMain
四、记住我 功能( Remember Me )
4.1. 创建 RememberMeConfig 配置类( + 建表)
4.2 修改登录页面( empLogin.html )
4.3 修改配置文件( MyConfig )
4.3.1 remember Me 功能设置
4.3.2 依赖注入
4.3.3 还可以设置有效时间
4.3.4 运行
4.3.4-1 如果不能自动创建保存我的信息表
4.4 代码没错,但就是运行不了 / 报错:
五、授权逻辑
5.1 新建数据库表
5.2 修改EmpMapper接口
5.3 添加 EmpMapper.xml 映射文件
5.3.1 如果 mapper 接口上没出现小鸟图标:
5.4 修改 EmpServiceImpl,为用户动态添加权限
5.5 修改配置类:为指定路径 设置权限
5.6 运行
5.7 添加错误页面
六、 整合 Thymeleaf
6.1 在 pom.xml 添加启动器
6.2 修改配置类 MyConfig
6.3 修改 success 页面
6.4 测试结果:
如果:ls 登录后也是四个功能:
七、退出 功能
7.1 修改 success 页面:添加退出链接
八、 CSRF
8.1 什么是 CSRF
8.2 Spring Security 中 CSRF
8.3 Spring Security 中 CSRF原理
8.4 实现步骤
8.4.2 修改配置类 MyConfig
九、重新编写退出功能
9.1 在配置类 MyConfig 添加完整的注销功能配置
9.2 修改成功页面( success.html )的注销功能
9.3 创建新的注销成功页面 logoutSuccess.html
9.4 运行
零、Spring Security 简介

Spring Security 是一个高度自定义的安全框架。利用 Spring IoC/DI 和 AOP 功能,为系统提供了声明式安全访问控制功能,减少了为系统安全而编写大量重复代码的工作。
“认证(authentication)”和“授权(authorization)”(或者访问控制)是 Spring Security 重要核心功能。“认证”,是建立一个他声明的主体的过程(一个“主体”一般是指用户,设备或一些可以在你的应用程序中执行动作的其他系统),通俗点说就是系统认为用户是否能登录。“授权”指确定一个主体是否允许在你的应用程序执行一个动作的过程。通俗点讲就是系统判断用户是否有权限去做某些事情。
需要有权限控制的项目都可以使用Spring Security。
一、创建一个Maven项目

1.1.添加启动器
在 pom.xml 的<project>里添加:
org.springframework.boot spring-boot-starter-parent 2.1.10.RELEASE 
    org.springframework.boot spring-boot-starter-web 2.1.10.RELEASE org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.1 mysql mysql-connector-java 8.0.30    org.springframework.boot 
spring-boot-starter-thymeleaf 2.1.10.RELEASE org.projectlombok lombok 1.16.18 provided org.springframework.boot 
spring-boot-starter-security 2.1.10.RELEASE 
org.apache.tomcat.maven tomcat7-maven-plugin 2.2 8080 / src/main/java **/*.xml src/main/resources **/*.yml **/*.xml **/*.html  // 很重要!!**/*.js  // 很重要!!**/*.properties  
在 Maven 项目中,pom.xml文件中的标签是有特定顺序要求的,常见的标签顺序:
1. 基础信息相关
- modelVersion(必须,且通常为 4.0.0)
 - groupId、artifactId、version(GAV 三要素,必须)
 - packaging(可选,默认 jar)
 - name、description、url等描述信息
 2. 依赖管理相关
- parent(父项目配置)
 - modules(聚合模块配置)
 - properties(属性定义)
 - dependencies(项目依赖)
 - dependencyManagement(依赖版本管理)
 3. 构建配置相关
- build(构建配置,包括sourceDirectory、plugins等)
 - profiles(环境配置文件)
 
        具体添加位置如下:
添加完刷新一下Maven(大部分不需要,我的需要这一步)
方法一:

方法二:

1.2 编写配置文件
1.2.1 创建配置文件
先在 src 的 main 包下创建一个 resources 目录

有这个 resources 就直接双击,没有就自己写然后按回车,创建完长这样 ↓↓↓


        如果你的 resources 长这样,没有橙色的横杠:
进入项目结构:项目--项目结构 / file(左上角的四条杠)--Project Strucrure

在 resources 下创建配置文件 application.yml (不要打错字了)

,回车
application.yml 长这样 ↓↓↓

1.2.2 编写配置文件
注意格式,注意最近,冒号后面必须有一个空格
按自己的具体情况修改端口号(8866),url中的数据库名(security),用户名,密码(root),包名(com.jr,pojo,com/jr/mapper/*.xml)等
server:port: 8866
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/security?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=trueusername: rootpassword: root
mybatis:type-aliases-package: com.jr.pojomapper-locations: classpath:com/jr/mapper/*.xmlconfiguration:  ##控制台输出sql语句log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
1.3 准备控制器

@Controller
public class EmpController {@RequestMapping("/show")public String show(){return "show";}
}
报红就点 import class

1.4 编写启动类
在 controller 包的上级包下面创建启动类 SpringBootMain 并编写内容,这里的注解 @MapperScan("com.jr.mapper"),要么在这写,要么在每个mapper接口上写 @Mapper
@SpringBootApplication
//@MapperScan("com.jr.mapper")
public class SpringBootMain {public static void main(String[] args) {SpringApplication.run(SpringBootMain.class,args);}
}

1.5 准备展示页面
在 resources下创建 templates,在 templates 里创建show.html 页面,在body里写内容


1.6 运行程序( SpringBootMain )
在浏览器输入:127.0.0.8866/show,会自动跳到 login 页面( Spring Security 自带的 )

用户名是 user,密码是控制台里输出的 ↓↓↓ 每次都不一样

就能进到show页面了

因为密码每次都不一样,退出刷新再用这个密码就登不了了

另外,如果是直接输入 127.0.0.1:8866/login ,登录成功也会出现404错误
因为本身跳到 login 页面只是拦截,登录成功后Spring Security 默认会重定向到用户最初请求的页面(即 /login),但由于我们并没有实际开发 /login 这个页面(Spring Security 自带的登录页面是框架内部的,并非我们的 show.html),所以会出现 404 错误。
二、了解 Spring Security 认证的逻辑:
2.1.了解页面逻辑
在登录页右键点击查看网页源码

所以重新写登录页面时也要按这个逻辑写,表单的 method 叫 "post" ,表单的action属性指向后端处理登录请求的接口地址,用户名叫 "username",密码叫 " password" ,提交按钮的 type 要设为 "submit"
2.2.了解认证逻辑

2.3.0 建表,编写实体类,数据访问层(mapper)
emp表 Emp类


Mapper接口:在 java.com.jr.mapper 下创建
要么每个mapper接口上都写 @Mapper 注解,
要么在启动类(SpringBootMain)上面加一个注解:@MapperScan("com.jr.mapper")
//@Mapper
public interface EmpMapper {@Select("select * from emp where username=#{username}")Emp selectEmpByEname(String username);
}
2.3. 了解UserDetailsService接口逻辑:
2.3.1 创建一个业务层实现类 EmpServiceImpl,实现 UserDetailsService 接口
当什么也没有配置的时候,账号和密码是由 Spring Security 定义生成的。而在实际项目中账号和密码都是从数据库中查询出来的。 所以我们要通过自定义逻辑控制认证逻辑。如果需要自定义逻辑时,只需要实现 UserDetailsService 接口即可。
 <-- 创建,↓实现接口(+ @Service 注解)

按住 Ctrl点击 UserDetailsService 进入 UserDetailsService 接口查看 ↓↓↓

因为数据库中存入的密码是加密的,用户输入内容在数据库中是查询不到的。
2.3.2 在 EmpServiceImpl 重写 loadUserByUsername 方法
        右键点击Generate / alt+insert --> Override Methods --> 重写 loadUserByUsername 方法        
  一整个EmpServiceImpl 的代码 ↓↓↓
@Service
public class EmpServiceImpl implements UserDetailsService {@Autowiredprivate EmpMapper empMapper;@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {Emp emp = empMapper.selectEmpByEname(s);if (emp == null) {throw new UsernameNotFoundException("用户名不存在,登录失败!");}// AuthorityUtils.NO_AUTHORITIES:默认UserDetails user = new User(emp.getUsername(), emp.getPassword(), AuthorityUtils.NO_AUTHORITIES);return user;}
}
2.3.2-1 分析UserDetailsService接口中方法的返回值:
loadUserByUsername 方法的返回值 UserDetails 是一个接口 ↓↓↓
UserDetails 对象是SpringSecurity封装的,包含了 username 查到的对象的所有信息。

要想返回 UserDetails 的实例就只能返回接口的实现类。Spring Security 中提供了如下的实例。对于我们只需要使用里面的 User 类即可。注意 User 的全限定路径是:
org.springframework.security.core.userdetails.User 此处经常和系统中自己开发的 User 类弄混。 不要导错包了!!

其中构造方法有两个,调用其中任何一个都可以实例化UserDetails实现类User类的实例。而三个参数的构造方法实际上也是调用7个参数的构造方法。

username:用户名, password:密码, authorities:用户具有的权限。此处不允许为null

此处的用户名应该是客户端传递过来的用户名。而密码应该是从数据库中查询出来的密码。Spring Security 会根据 User 中的 password 和客户端传递过来的 password 进行比较。如果相同则表示认证通过,如果不相同表示认证失败。
2.3.3 编写测试类 DemoTest
在 test.java.com.jr 下创建测试类 DemoTest

public class DemoTest {@Testpublic void test1(){// 创建解析器PasswordEncoder encoder = new BCryptPasswordEncoder();// 对密码进行加密String password = encoder.encode("123");System.out.println("------------"+password);// 判断原字符加密后和内容是否匹配boolean result = encoder.matches("123",password);System.out.println("============="+result);}
}
2.3.3-1 报错:
@Test 报红:导包

test1 方法前面没有运行按钮(绿色的三角)就到 pom.xml 里添加依赖
    org.springframework.boot spring-boot-starter-test test  
install 后控制台报错:程序包 org.junit不存在

修改 pom.xml 中 junit 依赖的版本(可能是版本低了)修改后刷新 Maven,重新clean,install
 --> 
2.3.3-2 PasswordEncoder 接口
encode():把参数按照特定的解析规则进行解析。
matches():验证从存储中获取的编码密码与编码后提交的原始密码是否匹配。如果密码匹配,则返回 true;如果不匹配,则返回 false。第一个参数表示需要被解析的密码。第二个参数表示存储的密码。
upgradeEncoding():如果解析的密码能够再次进行解析且达到更安全的结果则返回 true,否则返回 false。默认返回 false。

2.3.3-3 了解SpringSecurity 的加密算法 ==> 密码解析器:
Spring security 中有多种密码加密方式,MD5 算法的 Md5PasswordEncoder、SHA 算法的 ShaPasswordEncoder,但由于是弱加密算法都被弃用了。推荐使用的是 BCrypt 算法的 BCryptPasswordEncoder。

 BCryptPasswordEncoder是Spring Security官方推荐的密码解析器,平时多使用这个解析器。BCryptPasswordEncoder是对bcrypt强散列方法的具体实现。是基于Hash算法实现的单向加密。可以通过strength控制加密强度,默认10。
2.3.4 运行 test1
右下角的弹窗都点这个 Enable annotation processing 就好了

输出的是 123 加密后的字符串,把这个写到 Emp 表的 password 字段(每次运行出来的都不一样,存哪个都行)


为什么加密同一个内容,多次执行后,结果不一样?因为概率问题,假如两个人的密码一样,加密后也一样。一旦知道其中一个人的密码,那么就会知道其他人的,不安全。
三、自定义登录页面
3.1 编写登录页面( empLogin.html )
在 templates下创建 empLogin.html   
在 body 里写:
这是一个(相对)漂亮的登录页面!
表单提交地址不指定默认是login;此时访问当前登录页面,需要地址栏输入具体页面名称和地址访问。
3.2 修改控制类( EmpController )
@Controller
public class EmpController {@RequestMapping("/{url}")public String show(@PathVariable String url){return url;}
}
有了这个控制器类之后,地址里输入页面名称就可以,这样 ↓↓↓( 这是 MyConfig )

3.3 编写自定义配置类 MyConfig
在 src.main.java.com.jr 下创建 config 包,在里面创建 MyConfig 类

继承 WebSecurityConfigurerAdapter 类,重写 configure 方法(参数类型是 HttpSecurity,不要选错了),所有需要自定义的地方都在这方法里配置

一整个 MyConfig 的代码 ↓↓↓
@Configuration
public class MyConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {//1.配置表单认证:http.formLogin().loginProcessingUrl("/elogin") //配置自定义登录页面中 表单的action提交地址。使用默认/login,可以不进行配哦之.loginPage("/empLogin")    //登录页面对应地址.successForwardUrl("/success") //设置登录成功后的跳转页面.failureForwardUrl("/empLogin");//设置登录失败后的跳转页面,也可以再整一个 failure.html 页面//2.配置权限:http.authorizeRequests().antMatchers("/empLogin").permitAll() //设置路径放行.anyRequest().authenticated();  //设置路径拦截//3.关闭csrf防护http.csrf().disable();}/*指定SpringSecurity认证的加密算法*/@Beanpublic BCryptPasswordEncoder getBCryptPasswordEncoder(){return new BCryptPasswordEncoder();}
}
3.4 自定义登录成功和失败页面

3.5 编写登录成功后跳转的页面( success.html )
 位置:
         内容:
3.6 运行 SpringBootMain

在网址栏输入 127.0.0.1:8866/show ,会自动跳转到 127.0.0.1:8866/empLogin 页面

按 emp 表里的,输入 zs 和 123 再输入 127.0.0.1:8866/show 就可以跳转了


四、记住我 功能( Remember Me )
4.1. 创建 RememberMeConfig 配置类( + 建表)
在 config 包下创建 RememberMeConfig
@Configuration
public class RememberMeConfig {@Autowiredprivate DataSource dataSource;@Beanpublic PersistentTokenRepository getPersistentTokenRepository() {JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl = new JdbcTokenRepositoryImpl();jdbcTokenRepositoryImpl.setDataSource(dataSource);// 自动 建表 ,第一次启动时需要,第二次启动时注释掉 ↓jdbcTokenRepositoryImpl.setCreateTableOnStartup(true);return jdbcTokenRepositoryImpl;}
}
其中,倒数第二行的 jdbcTokenRepositoryImpl.setCreateTableOnStartup(true); 这段是用来建表的,第一次运行时会建表,运行完要注释掉,不然下次运行会报错。
↓↓↓ 报的错有点多,主要的是最后一张里标出来的那个 Table 'persistent_logins' already exists



4.2 修改登录页面( empLogin.html )
添加代码:记住我:<input type="checkbox" name="remember-me" value="true"/> <br/>

4.3 修改配置文件( MyConfig )
4.3.1 remember Me 功能设置
        //3.remember Me功能设置:http.rememberMe().userDetailsService(empService) // 登录逻辑交给哪个对象.tokenRepository(repository)   // 持久层对象.tokenValiditySeconds(60*30);   //设置 remember Me 的 token 值有效时间为30分钟
位置:

报红:在 MyConfig 类里加下面这个,进行自动配置↓↓↓
4.3.2 依赖注入
    @Autowiredprivate PersistentTokenRepository repository;@Autowiredprivate EmpServiceImpl empService;//EmpServiceImpl实现了SpringSecurity的认证接口的实现类
位置:

4.3.3 还可以设置有效时间
默认的有效时间是 14 天(1209600 秒)
上面( 4.3.1 )的 .tokenValiditySeconds(60*30) 就是,单位是秒
【说明】:重启服务器之后,仍然可以记住你!访问 /show,可以直接跳转到 show 页面,不会再要求登录了。
4.3.4 运行
先运行一遍 -- 建表)

到 RemenbermeConfig 注释掉建表的代码

在网址栏里输入:127.0.0.1:8866/show ,拦截到登录页面,输入信息,勾选“记住我”选项,登录


运行完去数据库找 persistent_logins 表:↓ 保存了这次登录的数据

重启项目(确定把建表的代码给注掉了),直接访问 127.0.0.1:8866/show 不会被拦截

4.3.4-1 如果不能自动创建保存我的信息表
可以使用建表语句:
-- 创建数据库 security ,创建数据库表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)
4.4 代码没错,但就是运行不了 / 报错:
在生命周期里 clean 再 install:↓ 在项目右侧找到 “m”,单击 1,2~5 双击

又或者试试刷新一下 maven 项目(然后再 clean,install ):
方法一:

方法二:在项目右击,滑到底部找到 Maven,点击 Sync Project

五、授权逻辑
5.1 新建数据库表





5.2 修改EmpMapper接口
//@Mapper
public interface EmpMapper {@Select("select * from emp where username=#{username}")Emp selectEmpByEname(String username);/*** 根据用户名查询用户权限* @param username* @return*/List selectPnameByUsername(String username);
} 
5.3 添加 EmpMapper.xml 映射文件
在 resources 的 com\jr\mapper 下创建(这里必须用斜杠)
xml 映射文件的路径要跟 Mapper 接口的一样,名字、方法名、参数类型、返回值类型都要一样
 --> 
 

5.3.1 如果 mapper 接口上没出现小鸟图标:
刷新 Maven ( 本篇的 4.4 )
5.4 修改 EmpServiceImpl,为用户动态添加权限
@Service
public class EmpServiceImpl implements UserDetailsService {@Autowiredprivate EmpMapper empMapper;@Autowiredprivate Emp emp;@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {Emp emp = empMapper.selectEmpByEname(s);if (emp == null) {throw new UsernameNotFoundException("用户名不存在,登录失败!");}
// ********这下面是添加,修改的********// 查询用户对应的权限List listPermission = empMapper.selectPnameByUsername(s);List listAuthority = new ArrayList();for(String permisssion : listPermission){listAuthority.add(new SimpleGrantedAuthority(permisssion));}return new org.springframework.security.core.userdetails.User(emp.getUsername(),emp.getPassword(),listAuthority);// AuthorityUtils.NO_AUTHORITIES:默认/*UserDetails user = new User(emp.getUsername(), emp.getPassword(), AuthorityUtils.NO_AUTHORITIES);return user;*/}
}   
5.5 修改配置类:为指定路径 设置权限
修改 MyConfig 类的 "2.配置权限" 部分:( 就是添加 "/show" 那一行 )
意思是只有 拥有 emp:remove 权限的用户才能登录 show 页面
//2.配置权限:
http.authorizeRequests().antMatchers("/empLogin").permitAll() //设置路径放行.antMatchers("/show").hasAuthority("emp:remove") //为指定路径,设置权限.anyRequest().authenticated();  //设置路径拦截
5.6 运行
在浏览器中输入 http://localhost:8866/show 会要求进行登录认证,认证后如果用户具有emp:remove 权限会正常访问控制器,如果没有权限会报 403
· 用户 zs 登录,zs 是 rid 为 1 的管理员,有 pid 为 4 的 emp:remove 权限,登录成功后访问 show 页面会成功访问到
  --> 
· 用户 ls 登录,ls 是 rid 为 2 的普通用户,没有 pid 为 4 的 emp:remove 权限,登录成功后访问 show 页面会报 403 错误(权限不匹配)
  --> 
5.7 添加错误页面
方式一:设置具体的状态码页面
在 templates下,创建 error 文件夹,创建 错误状态码 .html 页面。 500----》500.html 404----》404.html
方式二:使用X进行模糊匹配
在 templates下,创建 error 文件夹,创建 数字+通配符 .html 页面。 535------5XX.html 404------4XX.htm
注意:40X 或者50X的格式是错误的!
方式三:统一错误显示页面
在 templates下,创建 error.html 页面。页面显示优先级:方式一(具体状态码页面) > 方式二(X模糊匹配) > 方式三(统一的错误显示页面)



在 pom.xml 文件的最底下的 <includes> 里配置资源文件的包含规则,使它可以识别后缀为 .png 和 .jpg 的文件:(添加后刷新maven)
          **/*.png **/*.jpg 
添加位置:

运行:登录 ls ,访问 show 页面

六、 整合 Thymeleaf
Spring Security 可以在一些视图技术中进行控制显示效果。例如:JSP 或 Thymeleaf。在非前后端分离且使用 Spring Boot 的项目中多使用 Thymeleaf 作为视图展示技术。
Thymeleaf 对 Spring Security 的支持都放在 thymeleaf-extras-springsecurityX 中,目前最新版本为 5。所以需要在项目中添加此 jar 包的依赖和 thymeleaf 的依赖。
6.1 在 pom.xml 添加启动器
然后刷新Maven
    org.thymeleaf.extras thymeleaf-extras-springsecurity5 3.0.4.RELEASE 
6.2 修改配置类 MyConfig
        //2.配置权限:http.authorizeRequests().antMatchers("/empLogin").permitAll() //设置路径放行.antMatchers("/show").hasAuthority("emp:findAll") //认证后,为指定路径,设置权限.antMatchers("/save").hasAuthority("emp:save").antMatchers("/remove").hasAuthority("emp:remove").antMatchers("/edit").hasAuthority("emp:edit").anyRequest().authenticated(); //设置路径拦截,认证后才可以访问!
添加对应的页面:save.html,remove.html,edit.html
6.3 修改 success 页面
最顶上的 xmlns:th 和 xmlns:sec :在html页面中引入 thymeleaf 命名空间和 security 命名空间
Title 添加
修改
查询
删除
6.4 测试结果:
不用权限的用户,登录成功后,看到的success页面的链接个数,是不一样的


如果:ls 登录后也是四个功能:
1、确认数据库中的 ls 对应的rid(1是管理员,2是普通用户)
2、在 pom.xml 中确认thymeleaf 依赖的版本:是 <version>2.1.10.RELEASE</version>

七、退出 功能
用户只需要向 Spring Security 项目中发送 /logout 退出请求即可。
7.1 修改 success 页面:添加退出链接
退出登录



【说明】:点击 /logout 后,Spring Security 默认自动跳转到 login 页面!当然也可以设置自定义跳转策略,设置自定义退出登录页面 ; 同时还会删除掉数据库中,Remember Me 功能的数据!
登录后,退出前的 persistent_logins 表:刷新 --> 多一条数据(过期的不会自动删除,会留着

点击退出登录回到登录页面 ↓

刷新表:zs 的数据都删没了

八、 CSRF
8.1 什么是 CSRF
CSRF(Cross-site request forgery)跨站请求伪造,是通过伪造用户请求访问受信任站点的非法请求访问。
跨域:只要网络协议,ip地址,端口中任何一个不相同就是跨域请求。
客户端与服务进行交互时,由于 http 协议本身是无状态协议,所以引入了cookie 进行记录客户端身份。在 cookie 中会存放 session id 用来识别客户端身份的。在跨域的情况下,session id 可能被第三方恶意劫持,通过这个 session id 向服务端发起请求时,服务端会认为这个请求是合法的,可能发生很多意想不到的事情。

8.2 Spring Security 中 CSRF
从Spring Security4 开始 CSRF 防护默认开启。默认会拦截请求。进行 CSRF 处理。CSRF 为了保证不是其他第三方网站访问,要求访问时携带参数名为 _csrf 值为 token(token 在服务端产生)的内容,如果 token 和服务端的 token 匹配成功,则正常访问。
8.3 Spring Security 中 CSRF原理
当服务器加载登录页面。(loginPage中的值,默认/login),先生成 csrf 对象,并放入作用域中,key 为 _csrf。之后会对 ${_csrf.token} 进行替换,替换成服务器生成的 token 字符串。
用户在提交登录表单时,会携带 csrf 的 token。如果客户端的 token 和服务器的 token 匹配说明是自己的客户端,否则无法继续执行。
用户退出的时候,必须发起 POST 请求,且和登录时一样,携带 csrf 的令牌。
8.4 实现步骤
8.4.1 所有页面都要添加 csrf 防护:
    

8.4.2 修改配置类 MyConfig
取消:关闭 csrf 防护

九、重新编写退出功能
额。。退出功能出错了,重新写了一个
9.1 在配置类 MyConfig 添加完整的注销功能配置
        //4.配置注销功能http.logout().logoutUrl("/logout")  // 设置注销的URL.logoutSuccessUrl("/logoutSuccess")  // 注销成功后跳转到注销成功页面.invalidateHttpSession(true);  // 使会话失效
这样 ↓ 更新了权限配置,允许匿名访问 /logoutSuccess 路径

9.2 修改成功页面( success.html )的注销功能
这样 ↓

9.3 创建新的注销成功页面 logoutSuccess.html
    注销成功!
您已成功退出系统。
返回登录页面
9.4 运行

ok呀差不多了,要是还有什么错误可以评论或者私信我
之后要是发现什么问题了也会进行修改更新的