Spring Security:如何从SecurityContextHolder的JWT中提取Subject
解决方案
直接处理Jwt类型
你的代码未针对Jwt类型做分支判断,导致走到else分支返回整个令牌字符串。修改代码,增加对Jwt实例的判断,直接调用getSubject()方法获取主题:
import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.context.SecurityContextHolder; // 获取Principal Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); String subject; // 判断是否为Jwt类型 if (principal instanceof Jwt) { subject = ((Jwt) principal).getSubject(); } else if (principal instanceof UserDetails) { subject = ((UserDetails) principal).getUsername(); } else { subject = principal.toString(); }
更简洁的方式:使用@AuthenticationPrincipal注解
在控制器方法参数中直接注入Jwt对象,无需手动从SecurityContextHolder获取:
import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.GetMapping; @GetMapping("/your-endpoint") public String getCurrentSubject(@AuthenticationPrincipal Jwt jwt) { return jwt.getSubject(); }
自定义Principal(可选)
如果希望将Principal转换为自定义对象(比如你的用户实体),可以配置JwtAuthenticationConverter:
- 定义转换器Bean:
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.context.annotation.Bean; @Bean public JwtAuthenticationConverter jwtAuthenticationConverter() { JwtAuthenticationConverter converter = new JwtAuthenticationConverter(); // 自定义Principal转换逻辑,这里直接返回subject,也可以返回自定义UserDetails实现 converter.setPrincipalClaimConverter(jwt -> jwt.getSubject()); return converter; }
- 将转换器添加到Security配置中:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { return http .httpBasic().disable() .csrf().disable() .formLogin().disable() .anonymous().disable() .logout().disable() .authorizeHttpRequests(authorize -> authorize .antMatchers("/actuator/**").permitAll() .antMatchers("/gicar/**").permitAll() .anyRequest().authenticated() ) .oauth2ResourceServer(config -> config.jwt(jwtConfig -> jwtConfig.jwtAuthenticationConverter(jwtAuthenticationConverter())) ) .build(); }
配置完成后,Principal将直接是你定义的类型(比如subject字符串),原有代码的else分支也能正确获取到主题。
内容的提问来源于stack exchange,提问作者Jordi
相关产品推荐
相关产品推荐

