使用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 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 ) );
}
}
注册bean
@Configuration
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 );
}
}
最后就可以像spring security一样。
使用SecurityContextHolder.getContext().getAuthentication().getPrincipal()获取用户信息了。