8

devo server di autorizzazione OAuth2 che fornisce informazioni all'utente:Spring Security OAuth2 - Come utilizzare l'oggetto OAuth2Authentication?

public class User implements Serializable, UserDetails { 
    private Long userID; 
    private String username; 
    private String password; 
    private String fullName; 
    private String email; 
    private String avatar; 
    private boolean enabled; 
    // etc 
} 

@RestController 
@RequestMapping("/api") 
public class APIController { 

    @RequestMapping("/me") 
    public User me(@AuthenticationPrincipal User activeUser) { 
     return activeUser; 
    } 
} 

Inoltre ho implementato cliente OAuth2 come applicazione di primavera di avvio separato.

@Configuration 
@EnableOAuth2Sso 
public class OAuth2ClientConfig extends WebSecurityConfigurerAdapter { 

    @Override 
    public void configure(HttpSecurity http) throws Exception { 
     http.logout() 
      .and() 
      .antMatcher("/**").authorizeRequests() 
      .antMatchers("/login").permitAll() 
      .anyRequest().authenticated(); 
    } 
} 

application.yml

security: 
    user: 
    password: none 
    oauth2: 
    client: 
     clientId:  acme 
     clientSecret: acmepassword 
     accessTokenUri:  http://localhost:9080/sso/oauth/token 
     userAuthorizationUri: http://localhost:9080/sso/oauth/authorize 
    resource: 
     userInfoUri: http://localhost:9080/sso/api/me 

utente si autentica con successo:

@Controller 
public class MainController { 

    @RequestMapping(value = "/") 
    public String index(Principal principal) { 
     System.out.println(principal); 
     // or[email protected]c2e723e8: Principal: superadmin; Credentials: [PROTECTED]; Authenticated: true; Details: remoteAddress=<ADDRESS>, sessionId=<SESSION>, tokenType=bearertokenValue=<TOKEN>; Granted Authorities: {userRoleID=1, authority=ROLE_SUPERUSER} 
     OAuth2Authentication auth = (OAuth2Authentication) principal; 
     System.out.println(auth.getUserAuthentication().getDetails()); 
     // {userID=1, username=superadmin, password=***, fullName=SuperUser, [email protected], avatar=null, enabled=true ... 
     return "index"; 
    } 
} 

Ma io non riesco a capire come utilizzare oggetti OAuth2Authentication prevista nella mia applicazione. È quasi inutile.

Quando sto cercando di utilizzare qualsiasi tag di sicurezza Thymeleaf

<span sec:authentication="principal.fullName">Username</span> 
<span sec:authentication="principal.authorities">Authorities</span> 
<span sec:authentication="principal.userAuthentication.details.fullName">Usernames</span> 

.. la seguente eccezione si verifica: metodi

Error retrieving value for property "property name here" of authentication object of class org.springframework.security.oauth2.provider.OAuth2Authentication 

standard di sicurezza Primavera isUserInRole() non funziona troppo:

System.out.println(servletRequest.isUserInRole("ROLE_SUPERUSER")); 
// false 

Devo implementare il dialetto di sicurezza Thymeleaf personalizzato e hasRole() metho d? O forse esiste una soluzione più semplice?

+1

'principal' (come in' authentication.getPrincipal() ') è un genere un' STRING' quindi dubito che ha diverse proprietà. –

+0

@M. Grazie per il tuo commento! Trovato! I tag di Thymeleaf non funzionano perché dialect opera [security.core.Authentication] (https://github.com/spring-projects/spring-security/blob/master/core/src/main/java/org/springframework/security /core/Authentication.java) oggetto che non contiene il campo 'UserAuthentication' (dove sono archiviate le mie proprietà personalizzate). E credo che il metodo 'isUserInRole()' non funzioni perché ho usato l'oggetto personalizzato 'GrantedAuthority'.Quindi ho solo bisogno di sostituire 'Principal' con' User' e convertire le autorità in una raccolta adeguata. – Vespin

risposta

1

Ok, dopo aver scavato molto ho trovato una soluzione.

Per farla breve: il metodo ResourceServerTokenServices.loadAuthentication() deve essere sostituito per estrarre il principal e/o le autorità personalizzate dalla risposta del server di risorse OAuth2. Logica principale incapsulata nel metodo extractAuthentication().

Config

@Configuration 
@EnableOAuth2Sso 
public class OAuth2ClientConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private ResourceServerProperties sso; 

    @Autowired 
    private OAuth2RestOperations restTemplate; 

    @Override 
    public void configure(HttpSecurity http) throws Exception { 
     http.logout().and().antMatcher("/**").authorizeRequests().antMatchers("/login").permitAll().anyRequest() 
         .authenticated(); 
    } 

    @Bean 
    // very important notice: method name should be exactly "userInfoTokenServices" 
    public ResourceServerTokenServices userInfoTokenServices() { 
     CustomUserInfoTokenServices serv = new CustomUserInfoTokenServices(sso.getUserInfoUri(), sso.getClientId()); 
     serv.setTokenType(sso.getTokenType()); 
     serv.setRestTemplate(restTemplate); 
     return serv; 
    } 
} 

Servizio

public class CustomUserInfoTokenServices implements ResourceServerTokenServices { 
    // exactly the same as org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices 
    // except extractAuthentication() method 
} 

PS:

Nuova Primavera Boot versione fornisce API più flessibile. Vedi interfaccia PrincipalExtractor. Purtroppo è stato aggiunto solo 2 settimane fa e non è supportato nella versione attuale della stalla 1.3.5.RELEASE.

Spero che questo aiuti

+0

Stai chiamando/oauth/check_token sul server di autenticazione? –

Problemi correlati