spring oauth2如何获取当前登录用户信息

使用spring oauth2框架做授权鉴定。想获取当前用户信息怎么办?

我们知道spring oauth2是基于spring security的实现的。

spring security可以通过SecurityContextHolder.getContext().getAuthentication().getPrincipal()获取到当前用户信息。

而spring oauth2通过SecurityContextHolder.getContext().getAuthentication().getPrincipal()却只能拿到当前用户的用户名。

然而实际开发过程中,我们较常用到的大部分都是用户的id。

那么怎么通过配置获取当前用户的信息呢?

首先我们看下,为什么oauth2通过SecurityContextHolder.getContext().getAuthentication().getPrincipal()获取到的是用户名?

我们看下源码

DefaultUserAuthenticationConverter.java

public Authentication extractAuthentication( Map<String, ?> map )
    /* userClaimName是静态常量:username */
    if ( map.containsKey( userClaimName ) )
        Object                  principal   = map.get( userClaimName );
        Collection<? extends GrantedAuthority>  authorities = getAuthorities( map );
        /* 原因就是这里。如果userDetailsService为空,返回的就是用户名。 */
        if ( userDetailsService != null )
            UserDetails user = userDetailsService.loadUserByUsername( (String) map.get( userClaimName ) );
            authorities = user.getAuthorities();
            principal   = user;
        return(new UsernamePasswordAuthenticationToken( principal, "N/A", authorities ) );
    return(null);

那我们就给这个类,设置userDetailsService。

我们看下这个类的调用。

DefaultAccessTokenConverter.java

public class DefaultAccessTokenConverter implements AccessTokenConverter {
    /* 一开始就被初始化好了,所以不能设置userDetailsService */
    private UserAuthenticationConverter userTokenConverter = new DefaultUserAuthenticationConverter();
    /* 但是提供了setter接口,所以我们要做的就是覆盖上面的实例。 */
    public void setUserTokenConverter( UserAuthenticationConverter userTokenConverter )
        this.userTokenConverter = userTokenConverter;

所以如果是使用DefaultAccessTokenConverter的,代码可以这么写

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
    @Override
    public void configure( AuthorizationServerEndpointsConfigurer endpoints ) throws Exception
        endpoints.tokenStore( tokenStore )
        .authenticationManager( manager )
        .allowedTokenEndpointRequestMethods( HttpMethod.GET, HttpMethod.POST )
        .userDetailsService( userService )
        /* .accessTokenConverter(tokenConverter); */
        DefaultAccessTokenConverter converter = new DefaultAccessTokenConverter();
        DefaultUserAuthenticationConverter userAuthenticationConverter
            = new DefaultUserAuthenticationConverter();
        userAuthenticationConverter.setUserDetailsService( userService );
        converter.setUserTokenConverter( userAuthenticationConverter );
        endpoints.accessTokenConverter( converter );

如果是用jwtConverter的话,可以这么改。

定义一个accessTokenConverter继承DefaultAccessTokenConverter

public class OauthAccessTokenConverter extends DefaultAccessTokenConverter {
    public OauthAccessTokenConverter( SecurityUserService userService )
        DefaultUserAuthenticationConverter converter = new DefaultUserAuthenticationConverter();
        converter.setUserDetailsService( userService );
        super.setUserTokenConverter( converter );

定义一个jwtConverter继承JwtAccessTokenConver

public class OauthJwtAccessTokenConverter extends JwtAccessTokenConverter {
    public OauthJwtAccessTokenConverter( SecurityUserService userService )
        super.setAccessTokenConverter( new OauthAccessTokenConverter( userService ) );
public class TokenConfig {
    @Bean
    public TokenStore jwtTokenStore( JwtAccessTokenConverter converter )
        return(new JwtTokenStore( converter ) );
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter( SecurityUserService userService )
        JwtAccessTokenConverter accessTokenConverter = new OauthJwtAccessTokenConverter( userService );
        accessTokenConverter.setSigningKey( "sign_key" );
        return(accessTokenConverter);

Oauth2认证服务

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private AuthenticationManager manager;
    @Autowired
    private SecurityUserService userService;
    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private JwtAccessTokenConverter tokenConverter;
    @Override
    public void configure( AuthorizationServerEndpointsConfigurer endpoints ) throws Exception
        endpoints.tokenStore( tokenStore )
        .authenticationManager( manager )
        .allowedTokenEndpointRequestMethods( HttpMethod.GET, HttpMethod.POST )
        .userDetailsService( userService )
        .accessTokenConverter( tokenConverter );