2015-04-24 20 views
7

Sto provando a eseguire un'applicazione di esempio utilizzando il boot primaverile e la sicurezza spring oauth con un JdbcTokenStore e un DefaultTokenServices configurati con token di accesso illimitati.spring security oauth2 ClassCastException che configura DefaultTokenServices

Esecuzione di questa applicazione con gradle bootRun, l'applicazione non verrà avviata e genera un "Causato da: java.lang.ClassCastException: com.sun.proxy. $ Proxy51 non può essere trasmesso a org.springframework.security.oauth2. provider.token.DefaultTokenServices "

Perché è presente un proxy attorno al bean DefaultTokenServices?

Una cosa strana è: eseguire l'applicazione con InMemoryTokenStore ... tutto funziona correttamente (vedi il ramo Inmemory).

Source Code https://github.com/grafjo/oauth_demo/blob/master/src/main/java/demo/AuthorizationServerConfiguration.java

traccia completa: http://pastebin.com/SUcwz4S5

+0

L'ho riscontrato quando avevo il supporto per le transazioni abilitato per JPA. Il tuo '@ SpringBootApplication' sta probabilmente configurando automaticamente un'origine dati transazionale, sì? Ho sicuramente rintracciato il mio progetto non-spring-boot in ''. Una volta commentato, il mio servizio di autorizzazione è stato configurato correttamente. Non sono sicuro di quale sia il conflitto preciso, ma sono abbastanza sicuro che ci sia un bug sistemico qui. Prova a disabilitare le transazioni solo per verificare. – MattSenter

+0

Sei sicuro di volere token di accesso illimitati ?! Questo sconfigge praticamente lo scopo di avere oauth. Forse durata infinita per il token di aggiornamento. – nucatus

risposta

7

Un rapido sguardo all'interno di DefaultTokenService rivela che è annotato con @Transactional. Spring lo avvolgerà in un proxy per servire le transazioni - di conseguenza è necessario interagire con la classe tramite la sua interfaccia.

Per la vostra tokenService di fagioli:

@Bean 
public DefaultTokenServices tokenServices() { 
    final DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); 
    defaultTokenServices.setAccessTokenValiditySeconds(-1); 
    defaultTokenServices.setTokenStore(tokenStore()); 
    return defaultTokenServices; 
} 

prova a cambiare a questo:

@Bean 
public AuthorizationServerTokenServices tokenServices() { 
    final DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); 
    defaultTokenServices.setAccessTokenValiditySeconds(-1); 
    defaultTokenServices.setTokenStore(tokenStore()); 
    return defaultTokenServices; 
} 
+0

sì che funziona. Ma come viene avviato questo bean all'interno di ResourceServerConfiguration che cerca un'interfaccia ResourceServerTokenServices? Ovviamente DefaultTokenServices implementa anche quell'interfaccia, ma quando la esponiamo come bean restituendo solo AuthorizationServerTokenServices, non dovrebbe essere autorizzata solo nelle classi che cercano implementazioni AuthorizationServerTokenServices? – Marios

+1

ok, ho trovato la risposta al commento precedente me stesso. in primavera i documenti di riferimento menzionano che "Se l'oggetto target da proxy implementa almeno un'interfaccia, verrà utilizzato un proxy dinamico JDK .Tutte le interfacce implementate dal tipo di destinazione verranno proxy. Se l'oggetto target non implementa alcun interfacce quindi verrà creato un proxy CGLIB. " Pertanto, il bean viene effettivamente iniettato in qualsiasi classe che abbia bisogno di una qualsiasi delle sue interfacce, non solo quella restituita. Supponendo che questo non fosse vero non avevo nemmeno provato la tua soluzione prima di pubblicarla :) – Marios

3

ho avuto una simile eccezione nella mia applicazione troppo, e quando si cambia la versione OAuth primavera da 2.0.7.RELEASE a 2.0.3.RELEASE ha funzionato. Forse è un bug nelle versioni latests?

EDIT: dall'errore sembra che il problema sia correlato ai proxy creati dalla molla. Quando cambio il tipo di proxy su CGLIB invece dei proxy dinamici predefiniti, funziona anche con la versione 2.0.7. Questa impostazione può essere impostata tramite la proprietà proxyTargetClass @EnableTransactionManagement(proxyTargetClass = true)

Tuttavia questa soluzione non è interessante per me poiché preferisco il metodo di proxy predefinito piuttosto che CGLIB. Qui c'è anche un articolo che spiega i metodi di proxying http://thecafetechno.com/tutorials/spring/spring-proxying-mechanisms/

+0

Il downgrade a 2.0.3.RELEASE funziona anche per me – joo

1

Questo funziona con la versione 2.0.7.RELEASE

@Primary 
@Bean 
protected AuthorizationServerTokenServices tokenServices() throws Exception{ 

Dopo aver modificato DefaultTokenServices a AuthorizationServerTokenServices, Spring genererà un errore:

No qualifying bean of type [org.springframework.security.oauth2.provider.token.ResourceServerTokenServices] is defined: expected single matching bean but found 3: defaultAuthorizationServerTokenServices,consumerTokenServices,tokenServices"}}

+0

questo risolve il mio problema. grazie: D –

0

ho avuto lo stesso problema con 2.0.9.RELEASE nella seguente combinazione:

pom.xml:

...  
<spring.version>4.1.4.RELEASE</spring.version>  
<spring-security.version>3.2.5.RELEASE</spring-security.version> 
<spring-security-oauth2.version>2.0.9.RELEASE</spring-security-oauth2.version> 
... 

e aveva la stessa eccezione.

declassamento a

... 
<spring-security-oauth2.version>2.0.3.RELEASE</spring-security-oauth2.version> 
... 

risolto il problema per me.

0

aggiungere

<aop:config proxy-target-class="true"/> 

della configurazione di primavera.

Problemi correlati