目录
项目源代码:https://github.com/maojianqiu/Demos/tree/main/springsecurity01/demo01
接下来学习基于表单认证的使用方式,由简单逐步深入学习,开始吧!
3.表单认证
默认的表单认证已经学了请看 2.3.3 ,现在产生了一些使用疑问,
1.不想使用security自带的登录页面,怎么自定义登录页面?(看 3.表单认证)
2.想使用数据库操作用户的增删改查怎么办?(看 4.认证与授权)
下面一一对应学习。
首先先解释一下 WebSecurityConfigurerAdapter 类中重写了三个 configure 方法:可跳过。
1.认证管理器配置方法 :void configure(AuthenticationManagerBuilder auth) ,配置认证管理器AuthenticationManager(后续会介绍到)
2.核心过滤器配置方法 :void configure(WebSecurity web),(一般不使用)
3.安全过滤器链配置方法:void configure(HttpSecurity http) ,(用来配置 HttpSecurity 。 HttpSecurity 用于构建一个安全过滤器链 SecurityFilterChain 。SecurityFilterChain 最终被注入核心过滤器 。 HttpSecurity 有许多我们需要的配置。我们可以通过它来进行自定义安全访问策略。(使用的最多,下面的就会使用到)
3.2自定义登录页面(demo01)
3.2.1自定义登录页面(demo01)
1.修改我们在 2.3.1 中添加的 WebSecurityConfig 类 ,security 的核心原理就在安全过滤链,所有我们会基于 void configure(HttpSecurity http) 进行修改。如下:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeHttpRequests()
.anyRequest().authenticated()
.and()
.formLogin()
//1.设置自定义的登录页面
.loginPage("/newlogin.html");
}
}
2.修改完之后,我们添加我们的自定义登录页面 /newlogin.html ,添加到 resources 下的 statis 文件中,这个文件放置的是静态内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>newlogin</title>
</head>
<body>
<div >登录系统</div>
<div >
账号:<input type="text" id="username" placeholder="请输入账号" />
</div>
<div >
密码:<input type="password" id="password" placeholder="请输入密码" />
</div>
<div >
<input type="button" value="登录" class="denglu" id="check" title="登录"> 
<input type="button" value="重置" class="denglu" id="chongzhi" title="重置">
</div>
</body>
</html>
运行打开 localhost:8080 ,发现时会自动跳转到 /newlogin.html ,但是页面出错了,如下图:

怎么会重定向呢?我们走一下流程:
未登录时系统默认打开 /newlogin.html 页面,而访问这个页面时也是请求也需要认证!然后系统又自动打开 /newlogin.html ,然后周而复始,就被判定为多次重定向!!!
所以我们切记,游客也就是所有人都能够访问的页面,一定要加入白名单,也就是一定要配置成不认证也能打开。
我们修改一下 security 的配置:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeHttpRequests()
//2.设置自定义登录页面和请求不设置访问权限
.antMatchers("/newlogin.html").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
//1.设置自定义的登录页面
.loginPage("/newlogin.html")
;
}
}
切记一定要把 .antMatchers("/newlogin.html").permitAll() 加到
.anyRequest().authenticated() 前面,因为 security 默认的匹配逻辑是从上往下匹配中了就返回,不会继续匹配完再选择具体按照哪一个匹配。
我们在运行打开看一下:
成功了........吗?登录页面是打开了,但是登陆成功后为什么是 403 错误呢
403:意思为资源不可用,服务器理解客户的请求,但拒绝处理它。

原因是 当我们继承 WebSecurityConfigurerAdapter 时会默认开启csrf()方法。这个方法是开启跨站请求伪造防护功能,(待扩展)
我们在配置中加上 .and().csrf().disable() 代码:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeHttpRequests()
//2.设置自定义登录页面和请求不设置访问权限
.antMatchers("/newlogin.html").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
//1.设置自定义的登录页面
.loginPage("/newlogin.html")
.and()
//关闭 csrf 防御
.csrf().disable();
}
}
添加之后访问成功!就不截图了,我去访问不存在的链接一定提示 404 。
3.2.2自定义登录请求(demo01)
处理好在自定义表单登录页之后,处理登录请求的URL可能也会相应改变。我们也可以自定义处理登陆请求。
1.在自定义登录页面后面追加相关配置 .loginProcessingUrl("/loginHandle")
.formLogin()
//设置自定义的登录页面
.loginPage("/newlogin.html")
//自定义登录请求 url ,注意登录页面的 form action 要修改为“/loginHandle”
.loginProcessingUrl("/loginHandle")
.and()
.csrf().disable();
2.既然自定义处理登录请求的URL,那我们应该也提供一下这个接口呀,我们创建一个 controller 文件夹,新增一个 LoginController 类,设置为 @Controller ,如下图

@Controller
@RequestMapping("/")
public class LoginController {
@RequestMapping("test01")
@ResponseBody
public String test01(){
System.out.println("------------newlogin------------");
return "trest01";
}
@RequestMapping(value ="loginHandle",method = RequestMethod.POST)
@ResponseBody
public String loginHandle(String username,String password){
System.out.println("------------loginHandle------------");
System.out.println(username+":"+password);
System.out.println("------------登陆成功------------");
return "loginHandle";
}
}
3.运行程序,打开链接访问,发现访问成功!!!!!!!!!!!等等,我们是不是忽略了什么?

控制台中并没有打出“------------登陆成功------------”呀,这个接口没有被访问,那怎么成功的呢?
原来:
security根本不会去请求我们自己写的 /loginHandle 这个接口!!!
loginProcessingUrl的作用是用来拦截前端页面对 /loginHandle 这个的请求的,拦截到了就走它自己的处理流程(也就是我们当前什么都没有配置的默认认证流程),所有我们自己后端写的 /loginHandle 这个接口有写跟没写是一样的。所以 loginProcessingUrl 这个值可以不用设置,然后前端登陆页面的form表单的action=""也行。
神奇呐,真的是这样吗?我们可以打断点来看一下,security 的认证流程是过滤链,其中默认的过滤链会有 UsernamePasswordAuthenticationFilter 这个类(具体是啥后面会学习到),我们打开这个类,找到 attemptAuthentication(...) 方法,这个是身份认证的方法,我们打上断点,然后 debug 运行 :

我们可以看到点击登录按钮时,会拦截到 /loginHandle 接口,所以是执行的security自己的认证方式,并且我们访问 /test01 是并没有拦截,因为这个是白名单,真相大白啦!
所以这个有点鸡肋,我们还是需要自己的认证方式和用户管理呀。
本文介绍了如何在Spring Security中自定义登录页面及登录请求URL,包括配置自定义登录页面、处理登录请求、解决常见问题等步骤。
-基于默认的表单认证实现自定义登录页面&spm=1001.2101.3001.5002&articleId=121977242&d=1&t=3&u=2a795796cd3d44f1b1737657d886831e)
1354

被折叠的 条评论
为什么被折叠?



