1. 程式人生 > 實用技巧 >spring oauth2獲取當前登入使用者資訊。

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));
}
}

  

註冊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()獲取使用者資訊了。