2015-03-30 16 views
9

C'è un modo per aggiungere un gestore di successo di accesso utilizzando spring-oauth2?spring-oauth2 gestore di accesso di successo

Ho provato a utilizzare il filtro di autenticazione di base ma filtra solo le credenziali del client e non le credenziali dell'utente.

Oppure è necessario creare un gestore di autenticazione utente personalizzato?

TIA

risposta

0

Abbiamo costruito un gestore di autenticazione personalizzato che abbiamo cablati in OAuth2AuthenticationProcessingFilter per ottenere questo fatto. Il metodo di autenticazione del gestore è in grado di decomprimere OAuth2Authentication e OAuth2AuthenticationDetails dal principal di autenticazione.

<bean id="oAuth2AuthenticationManager" class="org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager"> 
    <property name="resourceId" value="XXX-api"/> 
    <property name="tokenServices" ref="tokenServices"/> 
</bean> 

<bean id="resourceServerFilter" 
     class="org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter"> 
    <property name="authenticationManager" ref="oAuth2AuthenticationManager"/> 
    <property name="tokenExtractor"> 
     <bean class="com.xxx.oauth.BearerTokenExtractor"/> 
    </property> 
</bean> 
5

Questa soluzione funzionerà per il flusso di password e per altri non ne sono sicuro. Puoi aggiungere il tuo filtro personalizzato in posizione di "before = BASIC_AUTH_FILTER" nel tag http che è in oauth-server config, e puoi ottenere una risposta parsing di "oauth/token" quindi crea ByteArrayResponseWrapper per ottenere risposta, Qui I sto usando classe TeeOutputStream da "org.apache.commons commons-io",

private class ByteArrayResponseWrapper extends HttpServletResponseWrapper { 

    public ByteArrayResponseWrapper(ServletResponse response) { 
     super((HttpServletResponse) response); 
    } 

    private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 

    @Override 
    public ServletOutputStream getOutputStream() throws IOException { 
     return new DelegatingServletOutputStream(new TeeOutputStream(
       super.getOutputStream(), byteArrayOutputStream)); 
    } 

    public byte[] getByteArray() { 
     return this.byteArrayOutputStream.toByteArray(); 
    } 
} 

e ho creato estrattore token per separare il codice di estrarre access_token

public class OAuth2AccessTokenExtractor implements 
    OAuth2AccessTokenExtractor { 

private ObjectMapper mapper = new ObjectMapper(); 

public String getAccessTokenValue(byte[] response) { 
    try { 
     return mapper.readValue(response, OAuth2AccessToken.class) 
       .getValue(); 
    } catch (JsonParseException e) { 
     e.printStackTrace(); 
    } catch (JsonMappingException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    return null; 
} 

} 

dopo creare il doFilter filtro di esclusione come questo

private DefaultTokenServices tokenServices; 

private OAuth2AccessTokenExtractor tokenExtractor; 

@Override 
public void doFilter(ServletRequest request, ServletResponse response, 
     FilterChain chain) throws IOException, ServletException { 

    // create wrapper to read response body 
    ByteArrayResponseWrapper responseWraper = new ByteArrayResponseWrapper(
      response); 

    // led them go 
    chain.doFilter(request, responseWraper); 

    // get ClientAuthentication 
    Authentication clientAuthentication = SecurityContextHolder 
      .getContext().getAuthentication(); 

    // is authenticated or not to proceed 
    if (clientAuthentication != null 
      && clientAuthentication.isAuthenticated()) { 

     // callBack client authenticated successfully 
     onSuccessfulClientAuthentication(request, response, 
       clientAuthentication); 

     // check response status is success of failure 
     if (responseWraper.getStatus() == 200) { 

      // extract accessToken from response 
      String token = tokenExtractor 
        .getAccessTokenValue(responseWraper.getByteArray()); 

      if (token != null && !token.isEmpty()) { 

       // load authentication from token 
       OAuth2Authentication oAuth2Authentication = this.tokenServices 
         .loadAuthentication(token); 
       OAuth2AccessToken actualAccessToken = this.tokenServices 
         .getAccessToken(oAuth2Authentication); 

       // callBack user authenticated successfully 
       onSuccessfulUserAuthentication(request, response, 
         clientAuthentication, oAuth2Authentication, 
         actualAccessToken); 
      } else { 
       log.error("access token is empty from extractor"); 
      } 
     } else { 
      // callBack user authenticated failure 
      onFailureUserAuthentication(request, response, 
        clientAuthentication, request.getParameter("username")); 
     } 
    } else { 
     // callBack client authenticated failure 
     onFailClientAuthentication(request, response, 
       request.getParameter(OAuth2Utils.CLIENT_ID)); 
    } 
} 

protected void onSuccessfulClientAuthentication(ServletRequest request, 
     ServletResponse response, Authentication authentication) { 
} 

protected void onFailClientAuthentication(ServletRequest request, 
     ServletResponse response, String clientId) { 
} 

protected void onSuccessfulUserAuthentication(ServletRequest request, 
     ServletResponse response, Authentication clientAuthentication, 
     OAuth2Authentication userOAuth2Authentication, 
     OAuth2AccessToken token) { 
} 

protected void onFailureUserAuthentication(ServletRequest request, 
     ServletResponse response, Authentication clientAuthentication, 
     String username) { 
} 

durante la creazione dell'istanza del filtro inject tokenServices. ora onSuccessfulClientAuthentication, onFailClientAuthentication, onSuccessfulUserAuthentication e onFailureUserAuthentication saranno chiamati secondo la vostra autenticazione

per di più si può consultare questo codice su github

Modificato:

È possibile che questo frammento funziona bene quando si hanno di default risposta token e utilizza solo ServletResponseWrapper ed estraendo. Tuttavia, sembra ancora vulnerabile in modo da poter conoscere il successo dell'autenticazione dell'utente tramite la classe org.springframework.security.oauth2.provider.token.TokenEnhancer

Per ulteriori dettagli, vedere questo answer.

+0

Grazie. È al di là di me il motivo per cui gli autori di primavera oauth2 hanno rotto il design collaudato con semplici gestori di successi/fallimenti che hanno funzionato così bene in passato. –