在 Spring Security6 中,自定义登录请求参数名称(如将默认的 username 和 password 改为其他名称)需要通过配置 formLogin() 方法实现。以下是具体步骤和示例代码:
在 Security 配置类中,使用 usernameParameter() 和 passwordParameter() 方法指定自定义参数名:
package com.hxstrive.spring_security.config;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.ForwardAuthenticationFailureHandler;
import java.io.IOException;
import static org.springframework.security.config.Customizer.withDefaults;
/**
* Spring Security 配置类
* @author hxstrive.com
*/
@Configuration
public class SecurityConfig {
@Bean
public UserDetailsService userDetailsService() {
System.out.println("userDetailsService()");
return new CustomUserDetailsService();
}
@Bean
public PasswordEncoder passwordEncoder() {
System.out.println("passwordEncoder()");
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
System.out.println("securityFilterChain()");
// csrf 设置
// csrfCustomizer.ignoringRequestMatchers(*) 表示所有请求地址都不使用 csrf
http.csrf(csrfCustomizer -> csrfCustomizer.ignoringRequestMatchers("*"))
// authorize.anyRequest().authenticated() 表示所有的请求都需要进行身份验证。
.authorizeHttpRequests(authorize -> authorize
// 配置登陆失败页面访问不需要鉴权,如果不配置,不会跳转到登录失败页面
.requestMatchers("/view/fail").permitAll()
.anyRequest().authenticated())
// formLogin() 用于配置表单登录功能
.formLogin(e -> e.loginProcessingUrl("/login") // 配置处理登陆请求到地址
// 自定义登陆页面地址
.loginPage("/view/login")
// 自定义登陆参数【看这里】
.usernameParameter("myUsername") // 自定义用户名参数名称
.passwordParameter("myPassword") // 自定义密码参数名称
// 自定义登陆成功页面
.defaultSuccessUrl("/view/success")
// 登陆失败页面
.failureUrl("/view/fail")
.permitAll())
// httpBasic() 启用 HTTP 基本认证,withDefaults() 表示使用默认的 HTTP 基本认证配置。
.httpBasic(withDefaults());
return http.build();
}
}关键代码说明:
设置表单中用户名的参数名,默认为 username。源码如下:
/**
* 执行身份验证时用于查找用户名的HTTP参数,默认值为 “username”。
* @param usernameParameter 执行身份验证时用于查找用户名的HTTP参数
* @return the {@link FormLoginConfigurer} for additional customization
*/
public FormLoginConfigurer<H> usernameParameter(String usernameParameter) {
getAuthenticationFilter().setUsernameParameter(usernameParameter);
return this;
}设置表单中密码的参数名,默认为 password。源码如下:
/**
* 执行身份验证时用于查找密码的HTTP参数,默认值为 “password”。
* @param passwordParameter 执行身份验证时用于查找密码的HTTP参数
* @return the {@link FormLoginConfigurer} for additional customization
*/
public FormLoginConfigurer<H> passwordParameter(String passwordParameter) {
getAuthenticationFilter().setPasswordParameter(passwordParameter);
return this;
}修改登陆页面,确保 HTML 表单中的参数名与后续配置一致,如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>自定义登录</title>
</head>
<body>
<h1>自定义登录页面</h1>
<form action="/login" method="post">
<p>
<!-- 默认 name="username" -->
用户名:<input type="text" name="myUsername" placeholder="请输入用户名" />
</p>
<p>
<!-- 默认 name="password" -->
密码:<input type="password" name="myPassword" placeholder="请输入密码" />
</p>
<p>
<input type="submit" value="登录"/>
</p>
</form>
</body>
</html>配置完成后,重启项目即可。
📢 注意事项:
(1)参数名一致性:确保 HTML 表单中的 name 属性与 usernameParameter() 和 passwordParameter() 配置一致。
(2)CSRF 保护:如果启用了 CSRF 保护(默认启用),表单需包含 CSRF 令牌(可通过 Thymeleaf 自动注入,也可以关闭 CSRF 保护)。
(3)参数类型:参数类型必须为 String,Spring Security 会自动处理编码问题。
Spring Security 中,当进行登录时会执行 UsernamePasswordAuthenticationFilter 过滤器,下面是该过滤器成员变量的定义,如下图:

注意,上面成员变量中,postOnly=true 表示默认情况下只允许 POST 请求。
为了更进一步了解信息,我们可以在 attemptAuthentication(HttpServletRequest, HttpServletResponse) 方法上打一个断点进行观察,如下图:

继续查看“线程和变量”控制面板,展开 this 对象,发现我们设置到参数名称了吗?就是我们设置的参数“myUsername”和“myPassword”,如下图:

继续查看 attemptAuthentication() 方法中用于获取用户名和密码的方法 obtainUsername() 和 obtainPassword(),它们使用了我们设置的参数名称从 HttpServletRequest 中获取请求参数,如下图:

最终从 HttpServletRequest 中获取的参数信息如下图:

到这里,关于请求参数的源码分析完成。后续章节将介绍 Spring Security 自定义登录成功处理