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

Spring Boot+Spring Security环境下如何获取当前登录用户ID

获取Spring Security OAuth2中当前登录用户的ID

我来帮你解决这个问题——你现在只能拿到用户名是因为默认的UserDetails对象里没有用户ID字段,我们需要自定义UserDetails并整合到Spring Security的流程中,同时处理JWT的情况,这样就能轻松获取当前登录用户的ID了。

步骤1:自定义UserDetails实现

首先,我们需要创建一个自定义的UserDetails类,把你的用户实体中的id、name、email等字段都包含进去,这样登录后Authentication的Principal就是这个自定义对象:

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;

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

    // 从你的User实体转换构造
    public CustomUserDetails(User user, Collection<? extends GrantedAuthority> authorities) {
        this.id = user.getId();
        this.name = user.getName();
        this.email = user.getEmail();
        this.password = user.getPass();
        this.authorities = authorities;
    }

    // 重写UserDetails的必要方法
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    // 这里返回的是登录凭证,比如你用email登录就返回email,用name就返回name
    @Override
    public String getUsername() {
        return email;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    // 自定义方法获取用户ID
    public Long getId() {
        return id;
    }

    // 其他字段的getter(可选)
    public String getName() {
        return name;
    }

    public String getEmail() {
        return email;
    }
}

步骤2:实现UserDetailsService

接下来,在你的UserDetailsService实现中,查询数据库获取用户实体,然后转换成CustomUserDetails返回:

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collections;

@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 {
        // 根据登录凭证(这里假设是email)查询用户
        User user = userRepository.findByEmail(username)
                .orElseThrow(() -> new UsernameNotFoundException("用户不存在:" + username));

        // 这里可以从数据库查询用户的权限,暂时用空集合示例
        return new CustomUserDetails(user, Collections.emptyList());
    }
}

步骤3:在Controller中获取用户ID

现在你有两种方式在Controller中获取用户ID:

方式一:转换Authentication的Principal

@GetMapping("/userId")
@ResponseBody
public String currentUserId(Authentication authentication) {
    if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails) {
        CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
        return userDetails.getId().toString();
    }
    return "未登录";
}

方式二:使用@AuthenticationPrincipal注解(更简洁)

@GetMapping("/userId")
@ResponseBody
public String currentUserId(@AuthenticationPrincipal CustomUserDetails userDetails) {
    return userDetails.getId().toString();
}

步骤4:处理JWT场景(关键)

因为你用了Spring Security OAuth2的JWT,需要确保生成Token时把用户ID写入JWT的Claims中,这样资源服务器也能解析到ID:

自定义TokenEnhancer

import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class CustomTokenEnhancer implements TokenEnhancer {

    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
        CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
        Map<String, Object> additionalInfo = new HashMap<>();
        additionalInfo.put("userId", userDetails.getId());
        additionalInfo.put("name", userDetails.getName());

        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
        return accessToken;
    }
}

配置AuthorizationServer

在你的授权服务器配置中,把这个TokenEnhancer添加到Token链中:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import java.util.Arrays;

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private CustomUserDetailsService userDetailsService;

    @Autowired
    private CustomTokenEnhancer customTokenEnhancer;

    @Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(customTokenEnhancer, jwtAccessTokenConverter));

        endpoints.tokenStore(new JwtTokenStore(jwtAccessTokenConverter))
                .accessTokenConverter(jwtAccessTokenConverter)
                .tokenEnhancer(tokenEnhancerChain)
                .userDetailsService(userDetailsService);
    }

    // 记得配置ClientDetails和JwtAccessTokenConverter的签名密钥(比如对称密钥或非对称密钥)
}

如果你的资源服务器是独立的服务,还可以直接从JWT的Claims中获取ID:

@GetMapping("/userId")
@ResponseBody
public String currentUserId(Authentication authentication) {
    OAuth2Authentication oAuth2Auth = (OAuth2Authentication) authentication;
    Map<String, Object> claims = oAuth2Auth.getUserAuthentication().getDetails();
    Long userId = (Long) claims.get("userId");
    return userId.toString();
}

这样配置完成后,你就能轻松获取当前登录用户的ID了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 18:37:50