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
相关产品推荐
相关产品推荐

