Ich habe separaten Autorisierungsserver und Ressourcenserver. Der Autorisierungsserver verweist auf eine separate Datenbank. Ich habe CustomUserDetailService
für benutzerbezogene Informationen verwendet. Ich habe CustomTokenEnhancer
verwendet, um zusätzliche Informationen neben dem Token in der Antwort zu haben.Wie benutzerdefinierte UserDetailService-Objekt in Resource Server in Spring-Security-oauth2 erhalten?
@Configuration
public class OAuth2Configuration {
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter implements EnvironmentAware {
private static final String ENV_OAUTH = "authentication.oauth.";
private static final String PROP_CLIENTID = "clientid";
private static final String PROP_SECRET = "secret";
private static final String PROP_TOKEN_VALIDITY_SECONDS = "tokenValidityInSeconds";
private RelaxedPropertyResolver propertyResolver;
@Autowired
private DataSource dataSource;
@Autowired
private CustomUserDetailService userDetailsService;
@Bean
public TokenStore tokenStore() {
return new CustomTokenStore(dataSource);
}
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.tokenStore(tokenStore())
.userDetailsService(userDetailsService)
.tokenEnhancer(tokenEnhancer())
.accessTokenConverter(accessTokenConverter())
.authenticationManager(authenticationManager);
}
@Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
@Bean
public DefaultAccessTokenConverter accessTokenConverter() {
return new DefaultAccessTokenConverter();
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer)
throws Exception {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
}
}
CustomUserDetailService Klasse:
@Service
public class CustomUserDetailService implements UserDetailsService {
@Autowired
private AccountRepository accountRepository;
@Override
public UserDetails loadUserByUsername(String username) {
Account account = accountRepository.getByEmail(username);
if(account == null) {
throw new UsernameNotFoundException(username);
}
return new MyUserPrincipal(account);
}
}
CustomTokenEnhancer Klasse:
public class CustomTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
MyUserPrincipal user = (MyUserPrincipal) authentication.getPrincipal();
final Map<String, Object> additionalInfo = new HashMap<>();
additionalInfo.put("user_information", user.getAccount());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
}
Request/Response
http://localhost:9191/authserver/oauth/token
{
"access_token": "fddb571e-224e-4cd7-974e-65104dd24b41",
"token_type": "bearer",
"refresh_token": "eb412b00-9e4e-4d6c-86d8-324d999b5f08",
"expires_in": 100,
"scope": "read write",
"account_information": {
"id": 14,
"firstname": "name",
"lastname": "lastname",
}
}
Auf Seite Ressource-Server habe ich RemoteTokenSerice
t verwendet o Überprüfen Sie, ob das vom Benutzer angegebene Token gültig ist oder nicht.
@Configuration
@EnableResourceServer
public class OAuthResourceConfig extends ResourceServerConfigurerAdapter {
private TokenExtractor tokenExtractor = new BearerTokenExtractor();
@Override
public void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (tokenExtractor.extract(request) == null) {
SecurityContextHolder.clearContext();
}
filterChain.doFilter(request, response);
}
}, AbstractPreAuthenticatedProcessingFilter.class);
http.csrf().disable();
http.authorizeRequests().anyRequest().authenticated();
}
@Bean
public AccessTokenConverter accessTokenConverter() {
return new DefaultAccessTokenConverter();
}
@Bean
@Primary
public RemoteTokenServices remoteTokenServices(final @Value("${auth.server.url}") String checkTokenUrl,
final @Value("${auth.server.clientId}") String clientId,
final @Value("${auth.server.clientsecret}") String clientSecret) {
final RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
remoteTokenServices.setCheckTokenEndpointUrl(checkTokenUrl+"?name=value");
remoteTokenServices.setClientId(clientId);
remoteTokenServices.setClientSecret(clientSecret);
remoteTokenServices.setAccessTokenConverter(accessTokenConverter());
return remoteTokenServices;
}
}
So funktioniert Es ist richtig, und wenn ich einen Antrag stellen Server mit Token Ressourcen, verarbeitet es die Anfrage, ob das Token gültig ist. Meine Frage ist, ich möchte Account-Objekt in Ressourcenserver erhalten. Ich habe versucht, mit unter:
Account account = (Account)SecurityContextHolder.getContext().getAuthentication().getPrincipal()
Aber es gibt String und nicht das komplette Benutzerobjekt definieren und somit wirft es die exception.How Konto Objekt in jedem Controller in Ressource-Server zu bekommen?
{
"timestamp": 1499334657703,
"status": 500,
"error": "Internal Server Error",
"exception": "java.lang.ClassCastException",
"message": "java.lang.String cannot be cast to Account",
"path": "/secure"
}
Ich habe versucht, mit link aber ist es möglich, beide zwei Token Services, RemoteTokenService und CustomUserInfoTokenServices zu injizieren?
Auch ich denke, hier Frühjahr macht internen Aufruf von Resource Server zu Authorization Server (http://localhost:9191/authserver/oauth/check_token?token=d8dae984-7bd8-4aab-9990-a2c916dfe667), um das Token zu validieren.
Gibt es eine Möglichkeit, diese Informationen im Controller abrufen zu können, ohne diesen Endpunkt erneut aufzurufen.
Antwort:
{
"exp": 1499333294,
"account_information": {
"accountid": 14,
"firstname": "fname",
"lastname": "lname",
},
"user_name": "[email protected]",
"client_id": "clientId",
"scope": [
"read",
"write"
]
}