Spring Boot 3.3.0 OAuth2实践遇401错误及登录页跳转异常
问题分析与解决方案
问题根源
- 访问
/出现401:你配置了HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED),会让所有未认证请求直接返回401——包括页面中$.get("/user")这个需要认证的AJAX请求,导致页面加载后触发401错误,甚至被浏览器误认为是页面本身的响应错误。 - 移除CSRF配置跳转到默认登录页:Spring Security默认认证入口会在未认证时跳转至
/login,而你没有自定义该页面,因此会显示框架自动生成的登录页,而非你的index.html。
解决方案
1. 调整认证入口逻辑
替换原有的exceptionHandling配置,区分HTML请求与API请求:HTML请求重定向到自定义登录页(/),API请求返回401,既保留前端登录体验,又符合接口的错误返回规范。
修改后的SecurityFilterChain代码:
@Bean public SecurityFilterChain httpFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests((authCust) -> authCust .requestMatchers("/", "/error", "/webjars/**").permitAll() .anyRequest().authenticated() ) .exceptionHandling(e -> e .authenticationEntryPoint((request, response, authException) -> { String acceptHeader = request.getHeader("Accept"); if (acceptHeader != null && acceptHeader.contains("text/html")) { // HTML请求重定向到自定义登录页 response.sendRedirect("/"); } else { // API请求返回401 response.setStatus(HttpStatus.UNAUTHORIZED.value()); } }) ) .csrf(c -> c .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) ) .logout(logoutCust -> logoutCust .logoutSuccessUrl("/").permitAll() ) .oauth2Login(Customizer.withDefaults()); return http.build(); }
2. 确认静态资源位置
确保index.html放置在src/main/resources/static目录下,Spring Boot默认会从该目录加载静态资源,访问/时会自动返回该文件。
3. 确保/user端点存在
页面中的AJAX请求依赖/user端点返回用户信息,需添加如下代码实现该接口:
@GetMapping("/user") public Map<String, Object> getUserInfo(@AuthenticationPrincipal OAuth2User principal) { return Collections.singletonMap("name", principal.getAttribute("name")); }
4. 保留CSRF配置的正确性
CookieCsrfTokenRepository.withHttpOnlyFalse()的配置是正确的,它允许前端JS读取XSRF-TOKEN Cookie,并在POST请求(如登出)中携带X-XSRF-TOKEN请求头,避免CSRF验证失败。
内容的提问来源于stack exchange,提问作者Jacob Batista
相关产品推荐
相关产品推荐

