一、导入所需依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
</parent>
<!-- web 支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringSecurity依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- thymeleaf 模板 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
二、配置security 的用户名和密码
#配置security 的用户名和密码 spring: security: user: name: root password: 1234如果不知道该地方为什么这么配置,请移步上一篇文章,连接地址初识spring security (一),一文弄懂默认配置-CSDN博客
三、基于web方式开发,页面跳转配置
传统web应用开发,登录成功我们会做一次 redirect 或者一个forward 的操作,重新到一个新的页面,如主页等;
3.1 自定义登录页面地址,替换自带的登录框
重写 WebSecurityConfigurerAdapter中的configure(HttpSecurity http) 使其默认的表单登录验证失效;
3.1.1 配置登录的url以及放行路径
http.csrf().disable();//关闭csrf 防护
http.authorizeRequests()
.mvcMatchers("/index.page").permitAll()//放行登录页面,放行的需要写到前面,不放行的写到后面
.anyRequest().authenticated()// 除了上面这个路径放行,后面所有的都需要认证
.and()
.formLogin()// 表单登录验证
.usernameParameter("loginId")// 自定义登录用户名参数
.passwordParameter("pwd")// 自定义登录密码参数
.loginPage("/index.page")// 用来指定默认的登录页面,注意一旦自定义登录页面以后必须只能登录url
.loginProcessingUrl("/doLogin") //指定登录请求url
.successForwardUrl("/main/index.page");// 登录成功后,forward 的页面,区别在于地址栏还是 doLogin而不是 /main/index.page
3.2 定义登录成功后的页面跳转
1.使用 .successForwardUrl("/main/index.page");方式,该方式类似于一个 forward 在内部跳转,从下面图中我们观察到,这个跳转的url实际上是表单的action地址
3.2.1 .successForwardUrl("/main/index.page");
3.2.2.1 效果图
3.2.2 .defaultSuccessUrl("/main/index.page")
使用.defaultSuccessUrl("/main/index.page"); 跳转,实际上内部是使用了一个SavedRequestAwareAuthenticationSuccessHandler 处理,我们看到是内部进行了一个redirect的操作,我们之前登录第doLogin 现在直接是我们之前访问的一个资源,该方法有一个重载参数,默认是false 意思为,访问时候会带上上一次请求的资源路径,当登录成功后,会重定向最开始访问的资源;浏览器本来是请求 /hello.do 请求,登录成功后,立马重定向 hello.do页面了,没有使用的默认成功页面 main/index.page页面
3.2.2.1 效果图
3.2.3 defaultSuccessUrl("/main/index.page",true)
我们发现我本来访问的是受限资源 /hello.do资源,但是还是给我跳到了 main/index.page的页面了 ,所以2 和3的区别就是,是否每次都需要用自己定义的这个资源url,现在明白了两者之间的关系了吧;
3.2.3.1 效果图
3.2.4 AuthenticationSuccessHandler关系类图
从上可知,redirect用的是 SavedRequestAwareAuthenticationSuccessHandler ,而forwa 用的是 ForwardAuthenticationSuccessHandler
3.3 定义登录失败后的跳转
这个时候密码故意输错,这个时候又继续回到登录页面了,是不是有一个疑问,这错误信息怎么不展示呢,下面我们来跟随一下源码看如何拿到错误信息;
如果认证失败的话,进行一个redirect 跳转,具体看 3.3.6 断点
3.3.1 .failureUrl("/index.page") 失败后,我们让回到的页面
3.3.2 将登录错误信息展示到页面上,本节为源码
这个时候我们跟随断点来到了父类的 AbstractAuthenticationProcessingFilter看到了一个catche 方法unsuccessfulAuthentication(request, response, ex);
3.3.3 unsuccessfulAuthentication 方法 继续看里面方法
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,AuthenticationException failed)
3.3.4 进到 onAuthenticationFailure 方法
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception)
3.3.5 .defaultFailureUrl 变量
因为我们自己配置了,所以上面一个不会进入,我们看saveException 方法干了什么
3.3.6 可以看到错误信息一个放到request中,一个放到了session中
根据断点得知错误新的的key 为:SPRING_SECURITY_LAST_EXCEPTION ,那么是不是就可以取出错误信息展示到页面上就可以了呢,从而得到 failureUrl是一个redirect 操作;这个时候我们用thymeleaf 将错误信息展示出来就好了;
3.3.6.1 效果图
3.3.7 .failureForwardUrl("/index.page")
根据上面源码得知,该错误信息肯定是放到request中了,可以直接获取,那么在thymeleaf中直接获取,同时观察浏览器url ,也是一个forword 还是登录的那个url
<h2 th:text="${SPRING_SECURITY_LAST_EXCEPTION }">错误信息</h2>
3.3.7.1 效果图
3.3.7.2 源码
3.3.8 AuthenticationFailureHandler 关系图
Forwor 用的是 ForwardAuthenticationFailureHandler
Redirect 用的是SimpleUrlAuthenticationFailureHandler
源码链接: