Spring Boot WebSecurity配置问题:注册接口被拦截跳转登录页
问题描述
我是Spring Boot新手,尝试用WebSecurity构建登录页面,已连接PostgreSQL数据库且应用可正常运行。但配置安全类后,使用Postman向/api/v1/registration发送POST请求时,未收到预期的"it works"返回,而是被拦截跳转到登录页面。我不确定@Bean的使用是否正确,目前陷入困境。
相关代码
注册控制器
@RestController @AllArgsConstructor @RequestMapping(path = "api/v1/registration") public class RegistrationController { private RegistrationService registrationService; @PostMapping public String register(@RequestBody RegistrationRequest request){ return registrationService.register(request); } }
RegistrationService
@Service public class RegistrationService { public String register(RegistrationRequest request) { return "it works"; } }
WebSecurityConfig
@Configuration @AllArgsConstructor @EnableWebSecurity public class WebSecurityConfig { private final AppUserServices appUserServices; private final BCryptPasswordEncoder bCryptPasswordEncoder; @Bean public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception{ httpSecurity .csrf() .disable() .authorizeHttpRequests() .requestMatchers("/api/v*/registration/**") .permitAll() .anyRequest() .authenticated() .and() .formLogin(); return httpSecurity.build(); } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { return authenticationConfiguration.getAuthenticationManager(); } }
解决方案
问题出在三个关键点:表单登录对未认证POST请求的默认重定向行为、缺少认证提供者的绑定配置,以及路径匹配可以更精准。以下是修复后的完整配置:
@Configuration @AllArgsConstructor @EnableWebSecurity public class WebSecurityConfig { private final AppUserServices appUserServices; private final BCryptPasswordEncoder bCryptPasswordEncoder; @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth .requestMatchers("/api/v1/registration") // 精确匹配注册接口,避免过度匹配 .permitAll() .anyRequest() .authenticated() ) .formLogin(form -> form .loginPage("/login") // 自定义登录页面路径,默认是/login .permitAll() // 允许所有用户访问登录页面 ) // 针对API请求,未认证时返回401而非重定向,适配Postman等工具 .exceptionHandling(ex -> ex .authenticationEntryPoint((request, response, authException) -> { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); }) ); return http.build(); } @Bean public AuthenticationProvider authenticationProvider() { // 绑定用户服务和密码编码器,让Spring Security知道如何校验用户 DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); authProvider.setUserDetailsService(appUserServices); authProvider.setPasswordEncoder(bCryptPasswordEncoder); return authProvider; } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { return config.getAuthenticationManager(); } }
关键修改说明
- 精确路径匹配:把
/api/v*/registration/**改为/api/v1/registration,确保只有注册接口被放行,避免模糊匹配带来的意外问题。 - 添加AuthenticationProvider:你已经注入了
AppUserServices和BCryptPasswordEncoder,但没有告诉Spring Security如何使用它们来做认证。这个Bean会把两者绑定,完成用户信息加载和密码校验的逻辑。 - 调整未认证处理逻辑:默认情况下,Spring Security会把未认证的请求重定向到登录页面,这对API请求不友好。配置
authenticationEntryPoint后,API请求会返回401状态码,而注册接口因为被permitAll放行,不会触发这个拦截。
验证方法
- 重启应用后,用Postman发送POST请求到
/api/v1/registration,随便传一个符合RegistrationRequest结构的JSON(比如{"email":"test@example.com","password":"123456"}),应该能收到"it works"的响应。 - 访问其他需要认证的接口,会返回401错误;如果用浏览器访问,则会跳转到登录页面,符合预期。
内容的提问来源于stack exchange,提问作者user20879521
相关产品推荐
相关产品推荐

