You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成Keycloak:获取已认证用户ID及令牌属性方法

获取Spring Security中已认证用户的完整信息

如果你只通过@AuthenticationPrincipal拿到用户名,说明默认的UserDetails只包含基础字段。要获取id、email等扩展属性,有以下几种实用方案:

1. 自定义UserDetails扩展属性

Spring Security的核心用户信息载体是UserDetails,默认的User类只提供username、password和权限。你需要自己实现这个接口,添加所需的自定义字段:

步骤1:创建自定义UserDetails类

public class CustomUserDetails implements UserDetails {
    private final Long id;
    private final String email;
    private final String username;
    private final String password;
    private final Collection<? extends GrantedAuthority> authorities;

    // 全参构造方法
    public CustomUserDetails(Long id, String email, String username, String password, Collection<? extends GrantedAuthority> authorities) {
        this.id = id;
        this.email = email;
        this.username = username;
        this.password = password;
        this.authorities = authorities;
    }

    // 实现UserDetails的强制方法(按需返回布尔值,一般默认启用)
    @Override
    public boolean isAccountNonExpired() { return true; }
    @Override
    public boolean isAccountNonLocked() { return true; }
    @Override
    public boolean isCredentialsNonExpired() { return true; }
    @Override
    public boolean isEnabled() { return true; }

    // 自定义字段的getter
    public Long getId() { return id; }
    public String getEmail() { return email; }

    // 重写父接口的getter
    @Override
    public String getUsername() { return username; }
    @Override
    public String getPassword() { return password; }
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() { return authorities; }
}

步骤2:在UserDetailsService中返回自定义实例

修改你的用户详情服务,从数据库查询完整用户信息,封装成CustomUserDetails:

@Service
public class CustomUserDetailsService implements UserDetailsService {
    private final UserRepository userRepository;

    // 构造注入
    public CustomUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("用户不存在: " + username));

        // 转换为自定义UserDetails,传入id、email等字段
        return new CustomUserDetails(
                user.getId(),
                user.getEmail(),
                user.getUsername(),
                user.getPassword(),
                // 根据用户角色生成权限列表
                AuthorityUtils.createAuthorityList("ROLE_" + user.getRole())
        );
    }
}

2. 在代码中获取完整用户信息

方式1:使用@AuthenticationPrincipal直接注入

在控制器方法中,直接注入自定义的CustomUserDetails:

@GetMapping("/api/user/profile")
public ResponseEntity<Map<String, Object>> getProfile(@AuthenticationPrincipal CustomUserDetails userDetails) {
    Map<String, Object> profile = new HashMap<>();
    profile.put("id", userDetails.getId());
    profile.put("username", userDetails.getUsername());
    profile.put("email", userDetails.getEmail());
    return ResponseEntity.ok(profile);
}

方式2:从SecurityContextHolder获取

如果不在控制器中(比如服务类),可以通过上下文获取:

public void someBusinessLogic() {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (auth != null && auth.getPrincipal() instanceof CustomUserDetails) {
        CustomUserDetails userDetails = (CustomUserDetails) auth.getPrincipal();
        Long userId = userDetails.getId();
        String email = userDetails.getEmail();
        // 业务逻辑处理
    }
}

3. 若使用JWT令牌:直接解析Claims

如果你的认证基于JWT,令牌本身包含id、email等自定义Claims,可以直接解析令牌获取:

// 从请求头提取JWT令牌(去除Bearer前缀)
String token = request.getHeader("Authorization").replace("Bearer ", "");

// 解析令牌(替换为你的签名密钥)
Jws<Claims> jws = Jwts.parserBuilder()
        .setSigningKey(Keys.hmacShaKeyFor("your-signing-secret-key".getBytes(StandardCharsets.UTF_8)))
        .build()
        .parseClaimsJws(token);

Claims claims = jws.getBody();
Long userId = claims.get("id", Long.class);
String email = claims.get("email", String.class);
String username = claims.getSubject();

注意:确保签发JWT时已将id、email等字段写入Claims。

内容的提问来源于stack exchange,提问作者Luiz Cardoso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 04:50:02