Skip to content

自定义登录页面

1. 创建登录Controller

java
@Controller
public class LoginController {

    @GetMapping("/login")
    public String login() {
        return "login";
    }
}

2. 创建登录页面

编写login.html页面:

sh
<html>
<head>
    <meta charset="utf8">
    <title>用户登录</title>
</head>
<body>
<h1>登录表单</h1>
<div th:if="${param.error}" style="color:red">
    错误的用户名和密码.
</div>
<form action="${ctx.contextPath}/login" method="post">
    <div>
        <!--name必须为"username"-->
        <input type="text" name="username" placeholder="用户名"/>
    </div>
    <div>
        <!--name必须为"password"-->
        <input type="password" name="password" placeholder="密码"/>
    </div>
    <input type="submit" value="登录"/>
</form>
</body>
</html>

3. 配置SecurityFilterChain

java
@Configuration
public class WebSecurityConfig {

    @Bean
    @Order(SecurityProperties.BASIC_AUTH_ORDER)
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated());
        // 放开登录页面的访问权限
        http.formLogin(formLogin -> formLogin.loginPage("/login").permitAll());
        // api接口测试时关闭csrf校验
        http.csrf((csrf) -> csrf.disable());
        return http.build();
    }
}

如果不加上permitAll(),会导致/login路径会被认为是被保护的资源, 然后跳转到/login, 此时又被认为是被保护的资源,出现递归重定向问题,浏览器也会报错提示请求次数过多! Alt text 加上permitAll()后,运行测试:
Alt text

4. 自定义用户信息参数

在用户登录页面上,默认的用户名和密码参数分为是username,password, 如果页面传入参数对不上则无法实际做登录逻辑,原因在于UsernamePasswordAuthenticationFilter中默认就是获取username,password名称的参数:
Alt text 如果是前后端分离项目,登录的用户名密码参数和后端的不一样,而且不能修改,SpringSecurity也提供了解决办法:

java
@Configuration
public class WebSecurityConfig {

    @Bean
    @Order(SecurityProperties.BASIC_AUTH_ORDER)
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated());
        // 放开登录页面的访问权限
        http.formLogin(formLogin -> {
            formLogin.loginPage("/login")
                    .permitAll()
                    // 自定义请求参数名
                    .usernameParameter("myUsername")
                    .passwordParameter("mypoassword");
        });
        // api接口测试时关闭csrf校验
        // http.csrf((csrf) -> csrf.disable());
        return http.build();
    }
}

如果注释防御csrf攻击的代码,重新运行会发现页面源码中会有csrfToken:
Alt text