Spring Boot+JWT鉴权异常:Authorization头为空致401/403错误
Spring Security集成JWT遇到的403/401问题
问题详情
开发React+Spring Boot前后端分离应用,后端第一部分开发完成,集成Spring Security JWT时出现以下异常:
- 访问
localhost:8080返回403错误,已在SecurityConfiguration中将/加入permitAll() - Postman发送POST请求到
/api/auth/login(用户已存在数据库)返回401,request.getHeader("Authorization")返回null - 堆栈追踪显示错误出现在
JWTFilter.doFilterInternal的chain.doFilter处:访问localhost:8080时header值为Basic (字母数字串),但登录请求时header为null - 已添加Cors配置,确认
getHeader参数为Authorization,问题仍未解决
相关代码
SecurityConfiguration.java
package com.keyoflife.keyoflife.config; import com.keyoflife.keyoflife.services.UserDetailsLoader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 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.config.http.SessionCreationPolicy; 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.UsernamePasswordAuthenticationFilter; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import java.util.Arrays; @Configuration @EnableWebSecurity @Order(Ordered.HIGHEST_PRECEDENCE) public class SecurityConfiguration { private final UserDetailsLoader usersLoader; private final JwtFilter jwtFilter; public SecurityConfiguration(UserDetailsLoader usersLoader, JwtFilter jwtFilter) { this.usersLoader = usersLoader; this.jwtFilter = jwtFilter; } @Bean public PasswordEncoder passwordEncoder() { //TODO: remove this //get the hashed version of 'asdfasdf' to save in db //System.out.println(new BCryptPasswordEncoder().encode("asdfasdf")); return new BCryptPasswordEncoder(); } @Bean public AuthenticationManager authenticationManager(HttpSecurity http, PasswordEncoder passwordEncoder) throws Exception { AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class); authenticationManagerBuilder.userDetailsService(usersLoader).passwordEncoder(passwordEncoder); return authenticationManagerBuilder.build(); } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .csrf(AbstractHttpConfigurer::disable) .cors(Customizer.withDefaults()) .authorizeHttpRequests(auth -> auth .requestMatchers("/user-dash").authenticated() .requestMatchers(HttpMethod.OPTIONS,"/api/auth/**", "/login", "/").permitAll() ) .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .httpBasic(Customizer.withDefaults()) .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class) .formLogin((login) -> login .loginPage("/login") .failureUrl("/login") .defaultSuccessUrl("/user-dash")) /* Logout configuration */ .logout((logout) -> logout .logoutSuccessUrl("/")) .build(); } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.addAllowedOrigin("http://127.0.0.1:8080"); configuration.setAllowedMethods(Arrays.asList("GET", "POST")); configuration.setAllowedHeaders(Arrays.asList("Content-Type", "Authorization")); configuration.setAllowCredentials(true); // for cookies. bc everyone likes cookies UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } }
JWTFilter关键代码
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { // Get authorization header and validate final String header = request.getHeader("Authorization"); System.out.println(header); //ensure header has text and starts with "Bearer " if (!StringUtils.hasText(header) || (StringUtils.hasText(header) && !header.startsWith("Bearer "))) { chain.doFilter(request, response); //Access Denied Exception thrown here because header is null return; } //rest of method below }
内容的提问来源于stack exchange,提问作者BDorries
相关产品推荐
相关产品推荐

