Spring Security 6表单登录未创建登录控制器问题求助
Spring Security 6非Boot MVC项目默认表单登录404/405问题解决
问题背景
在Spring 6 MVC(非Boot)项目中集成Spring Security 6默认表单登录时,遇到以下问题:
- 访问
GET /login返回404错误,未生成预期的登录页面控制器 - 自定义登录页提交表单到
/login时返回405错误,登录请求未被正确处理
核心原因
Spring Boot会自动配置登录页面相关的控制器和资源,但非Boot MVC项目不会自动生成GET /login的控制器,同时需要手动确保Spring Security的登录处理过滤器能正确拦截POST /login请求。
解决方案
1. 修正Spring Security配置
修改SecurityConfig.java,明确允许访问登录页面,并配置登录处理路径:
package com.myapp.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity @EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true) public class SecurityConfig { @Bean public SecurityFilterChain filterChain(final HttpSecurity http) throws Exception { return http .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(requests -> requests .requestMatchers("/login") // 允许匿名访问登录页面 .permitAll() .requestMatchers("/secured") .hasAnyRole("USER") .anyRequest() .authenticated() ) .formLogin(form -> form .loginPage("/login") // 指定登录页面路径 .loginProcessingUrl("/login") // 指定登录提交的处理路径,由Security过滤器处理 .permitAll() ) .build(); } }
2. 手动编写登录页面控制器
创建处理GET /login的控制器,返回登录视图:
package com.myapp.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class LoginController { @GetMapping("/login") public String showLoginPage() { return "login"; // 对应视图文件名称,需确保视图解析器配置正确 } }
3. 创建登录页面视图
以Thymeleaf为例,在/WEB-INF/views/目录下创建login.html,表单提交路径指向/login:
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>登录页面</title> </head> <body> <form th:action="@{/login}" method="post"> <div> <label>用户名:<input type="text" name="username"></label> </div> <div> <label>密码:<input type="password" name="password"></label> </div> <button type="submit">登录</button> </form> </body> </html>
4. 确保MVC配置正确
配置Spring MVC的组件扫描和视图解析器,确保控制器和视图能被正确识别:
package com.myapp.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.thymeleaf.spring6.SpringTemplateEngine; import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver; import org.thymeleaf.spring6.view.ThymeleafViewResolver; @Configuration @EnableWebMvc @ComponentScan(basePackages = "com.myapp") // 扫描项目下的控制器、配置等组件 public class WebConfig implements WebMvcConfigurer { @Override public void configureViewResolvers(ViewResolverRegistry registry) { ThymeleafViewResolver resolver = new ThymeleafViewResolver(); resolver.setTemplateEngine(templateEngine()); resolver.setCharacterEncoding("UTF-8"); registry.viewResolver(resolver); } private SpringTemplateEngine templateEngine() { SpringTemplateEngine engine = new SpringTemplateEngine(); engine.setTemplateResolver(templateResolver()); return engine; } private SpringResourceTemplateResolver templateResolver() { SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); resolver.setPrefix("/WEB-INF/views/"); // 视图文件前缀路径 resolver.setSuffix(".html"); // 视图文件后缀 resolver.setTemplateMode("HTML"); resolver.setCharacterEncoding("UTF-8"); return resolver; } }
5. 注册Spring Security过滤器到Servlet容器
创建初始化类,自动注册Security过滤器链:
package com.myapp; import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer { // 无需额外代码,此类会自动将Security过滤器注册到Servlet容器 }
6. 配置DispatcherServlet初始化
创建Web应用初始化类,加载Spring配置:
package com.myapp; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import com.myapp.config.WebConfig; import com.myapp.config.SecurityConfig; public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{SecurityConfig.class}; // 根上下文加载Security配置 } @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{WebConfig.class}; // Servlet上下文加载MVC配置 } @Override protected String[] getServletMappings() { return new String[]{"/"}; // 处理所有请求 } }
验证
- 启动项目后访问
GET /login,应能正常显示登录页面 - 输入正确的用户名密码(需提前配置用户,比如在SecurityConfig中添加
UserDetailsServiceBean),提交后应能成功登录并访问/secured接口
内容的提问来源于stack exchange,提问作者JCvanDamme
相关产品推荐
相关产品推荐

