使用Spring Security从JWT令牌中提取当前登录的用户信息

我已经使用Spring Security Oauth2实现了JWT和LDAP身份验证。似乎工作正常,我可以使用LDAP凭据登录。

现在,有一个要求,我需要使用当前登录的用户信息将详细信息保存在数据库中-特别是当该用户添加/更新新记录时。我试图使用Spring安全方式使用

SecurityContextHolder.getContext().getAuthentication().getDetails()

但它不会返回我在JWT中拥有的所有信息。它只是返回远程IP,JWT令牌值和经过验证的true。它甚至不返回name()。

我是JWT的新手,所以不确定是否需要通过读取该令牌以及我们如何实现它来提取它。

任何指针将不胜感激。

谢谢。

回答:

您需要做的第一件事是在创建JWT时将用户信息存储在JWT内,然后在使用JWT时将其提取。我有一个类似的情况,我通过扩展双方解决它TokenEnhancerJwtAccessTokenConverter

我使用TokenEnhancer来将我的扩展类型的主体嵌入CustomUserDetailsJWT其他信息中。

public class CustomAccessTokenEnhancer implements TokenEnhancer {

@Override

public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {

Authentication userAuthentication = authentication.getUserAuthentication();

if (userAuthentication != null) {

Object principal = authentication.getUserAuthentication().getPrincipal();

if (principal instanceof CustomUserDetails) {

Map<String, Object> additionalInfo = new HashMap<>();

additionalInfo.put("userDetails", principal);

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

}

}

return accessToken;

}

}

然后Authentication在处理经过身份验证的请求时在构建对象时手动提取扩展的主体。

public class CustomJwtAccessTokenConverter extends JwtAccessTokenConverter {

@Override

public OAuth2Authentication extractAuthentication(Map<String, ?> map) {

OAuth2Authentication authentication = super.extractAuthentication(map);

Authentication userAuthentication = authentication.getUserAuthentication();

if (userAuthentication != null) {

LinkedHashMap userDetails = (LinkedHashMap) map.get("userDetails");

if (userDetails != null) {

// build your principal here

String localUserTableField = (String) userDetails.get("localUserTableField");

CustomUserDetails extendedPrincipal = new CustomUserDetails(localUserTableField);

Collection<? extends GrantedAuthority> authorities = userAuthentication.getAuthorities();

userAuthentication = new UsernamePasswordAuthenticationToken(extendedPrincipal,

userAuthentication.getCredentials(), authorities);

}

}

return new OAuth2Authentication(authentication.getOAuth2Request(), userAuthentication);

}

}

以及将AuthorizationServer其捆绑在一起的配置。

@Configuration

@EnableAuthorizationServer

public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

@Autowired

private AuthenticationManager authenticationManager;

@Autowired

private UserDetailsService userDetailsService;

@Autowired

private DataSource dataSource;

@Bean

public JwtAccessTokenConverter accessTokenConverter() {

CustomJwtAccessTokenConverter accessTokenConverter = new CustomJwtAccessTokenConverter();

accessTokenConverter.setSigningKey("a1b2c3d4e5f6g");

return accessTokenConverter;

}

@Bean

public TokenStore tokenStore() {

return new JwtTokenStore(accessTokenConverter());

}

@Bean

@Primary

public DefaultTokenServices tokenServices() {

DefaultTokenServices defaultTokenServices = new DefaultTokenServices();

defaultTokenServices.setTokenStore(tokenStore());

defaultTokenServices.setSupportRefreshToken(true);

return defaultTokenServices;

}

@Bean

public TokenEnhancer tokenEnhancer() {

return new CustomAccessTokenEnhancer();

}

@Bean

public PasswordEncoder passwordEncoder() {

return new BCryptPasswordEncoder();

}

@Override

public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

clients.jdbc(dataSource).passwordEncoder(passwordEncoder());

}

@Override

public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();

tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter()));

endpoints

.tokenStore(tokenStore())

.tokenEnhancer(tokenEnhancerChain)

.authenticationManager(authenticationManager)

.userDetailsService(userDetailsService);

}

@Override

public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {

security.passwordEncoder(passwordEncoder());

security.checkTokenAccess("isAuthenticated()");

}

}

然后,我可以像这样访问我的资源控制器中的扩展主体

@RestController

public class SomeResourceController {

@RequestMapping("/some-resource")

public ResponseEntity<?> someResource(Authentication authentication) {

CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();

return ResponseEntity.ok("woo hoo!");

}

}

希望这可以帮助!

以上是 使用Spring Security从JWT令牌中提取当前登录的用户信息 的全部内容, 来源链接: utcz.com/qa/435959.html

回到顶部