Spring Security 5认证提交后始终返回302重定向问题求助
嘿,我碰到过好多次这种Spring Security登录提交后跳回登录页的情况,结合你给出的SecurityConfig代码片段(虽然没写完,但从注入DataSource这点能猜到是用数据库做用户认证),这种302重定向本质是认证失败后Spring Security的默认跳转逻辑,下面是几个最可能的原因和对应的修复方案:
1. 登录表单参数名和Security默认值不匹配
Spring Security默认认的用户名参数是username,密码是password,如果你的login.jsp里表单字段名是别的(比如userName或者passWord),那Security根本拿不到正确的登录信息,自然认证失败跳回登录页。
怎么修:
要么改JSP里的字段名,要么在SecurityConfig里自定义参数名:
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login.jsp") // 指定你的自定义登录页 .usernameParameter("你的用户名字段名") // 比如你表单里是userName就填这个 .passwordParameter("你的密码字段名") // 比如是passWord就填这个 .permitAll(); }
2. 数据库查询用户/权限的SQL不对
你注入了DataSource,说明是用JDBC做用户认证,Spring Security的JdbcUserDetailsManager有默认的SQL模板,如果你的用户表、权限表结构和默认模板不匹配,就查不到用户,直接认证失败。
怎么修:
在SecurityConfig里显式写对SQL:
@Autowired private DataSource dataSource; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.jdbcAuthentication() .dataSource(dataSource) // 查询用户的SQL:参数是用户名,要返回用户名、密码、enabled(用户是否可用) .usersByUsernameQuery("SELECT username, password, enabled FROM users WHERE username = ?") // 查询权限的SQL:参数是用户名,返回用户名、权限标识 .authoritiesByUsernameQuery("SELECT username, authority FROM authorities WHERE username = ?"); }
注意两点:一是你的用户表必须有enabled布尔字段,二是密码必须是加密后的格式——Spring Security 5强制要求密码加密,明文绝对不行。
3. 没配置密码加密器
刚才提到密码要加密,如果你数据库里的密码是加密过的,但没在Security里配置对应的加密器,Security会认不出这个密码,导致认证失败。
怎么修:
配置一个密码加密器,比如常用的BCrypt:
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.jdbcAuthentication() .dataSource(dataSource) .usersByUsernameQuery(...) .authoritiesByUsernameQuery(...) .passwordEncoder(passwordEncoder()); // 把加密器关联上 }
要是测试阶段想偷懒用明文(绝对别放生产),可以用NoOpPasswordEncoder(虽然高版本标了过时,但测试用没问题):
@Bean public PasswordEncoder passwordEncoder() { return NoOpPasswordEncoder.getInstance(); }
4. 登录表单的提交地址错了
表单的action属性必须指向Spring Security的登录处理地址,默认是/login,如果你写成/login.jsp,那提交后就又回到登录页了,等于没触发认证逻辑。
怎么修:
检查login.jsp里的表单:
<form action="/login" method="post"> <input type="text" name="username" /> <input type="password" name="password" /> <button type="submit">登录</button> </form>
要是你在配置里自定义了登录处理地址(比如.loginProcessingUrl("/doLogin")),那表单action就得改成/doLogin。
5. CSRF保护的坑
Spring Security默认开着CSRF保护,如果你的登录表单没带CSRF token,请求会被直接拒绝,然后跳回登录页。
怎么修:
要么在表单里加CSRF token:
<form action="/login" method="post"> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> <!-- 用户名密码输入框 --> </form>
要么开发阶段临时关掉CSRF(生产环境别这么干):
@Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() // 禁用CSRF .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login.jsp") .permitAll(); }
内容的提问来源于stack exchange,提问作者AlpacaMan

