Spring Security获取Principal用户名抛NullPointerException,无法识别请求JWT令牌
问题原因及解决方案
1. 路径权限配置导致认证逻辑跳过
你在安全配置中给/persons路径设置了permitAll()属性,Spring Security 对标记为完全放行的路径默认不会执行身份认证流程,哪怕请求携带了有效JWT,也不会解析令牌填充SecurityContext,所以你拿到的身份信息默认是anonymousUser,直接调用principal.getName()就会触发空指针异常。
如果需要该路径同时支持未登录访问、登录用户可获取身份信息,不要用permitAll(),改为anonymous()即可,或者调整JWT过滤器的执行逻辑,让它在放行路径也正常执行令牌解析操作。
2. CORS未放行自定义请求头
你用自定义头x-access-token携带令牌,跨域场景下后端默认会过滤未显式放行的自定义请求头,导致过滤器读取不到对应值,调试时拿到的JWT自然为null。
你可以补充如下CORS配置放行自定义头:
@Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(List.of("http://localhost:4200")); config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); // 显式放行自定义的x-access-token请求头 config.setAllowedHeaders(List.of("x-access-token", "Content-Type")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; }
3. JWT过滤器读取逻辑错误
检查你自定义AuthTokenFilter类的令牌解析逻辑,确认两点:
- 是不是从
x-access-token请求头取值,而不是默认的Authorization头 - 是不是正确处理了
Bearer前缀,你携带的令牌前缀是Bearer,需要截取掉前7位后再解析JWT
正确的读取逻辑参考:
String tokenHeader = request.getHeader("x-access-token"); String jwt = null; if (tokenHeader != null && tokenHeader.startsWith("Bearer ")) { jwt = tokenHeader.substring(7); // 后续执行JWT校验、身份填充逻辑 }
4. 过滤器执行顺序校验
你当前配置中addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class)的逻辑是正确的,只要过滤器本身逻辑没有问题,就能在身份认证前完成令牌解析。
内容的提问来源于stack exchange,提问作者gosia koduje
相关产品推荐
相关产品推荐

