Domanda

Ho la seguente situazione: meccanismo di autorizzazione della mia applicazione è implementata utilizza la protezione di primavera. Gli strumenti di classe centrali AccessDecisionManager e utilizza gli elettori (ciascuno dei quali implementa AccessDecisionVoter ) per decidere se concedere l'accesso a qualche metodo o meno. L'algoritmo che collima i voti è personalizzato:

public class PermissionManagerImpl extends AbstractAccessDecisionManager {

    public void decide(
            Authentication authentication,
            Object object,
            ConfigAttributeDefinition config) throws AccessDeniedException {
        Iterator<?> iter = getDecisionVoters().iterator();
        boolean wasDenied = false;

        while (iter.hasNext()) {
            AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
            int result = voter.vote(authentication, object, config);

            switch (result) {
                // Some tallying calculations
            }
        }

        if (wasDenied) {
            throw new AccessDeniedException("Access is denied");
        }               
    }

}

Al momento negare un accesso ad un metodo, il client dell'applicazione è interessato a ottenere un'eccezione informativo che specifica esattamente perché l'accesso è negato. Ciò implica che passa alcune informazioni dagli elettori al gestore decisione. Purtroppo, l'unica informazione lo standard AccessDecisionVoter passa di nuovo al manager decisione è uno dei possibili valori di ritorno ( ACCESS_GRANTED , ACCESS_ABSTAIN o ACCESS_DENIED ).

Qual è il modo migliore per farlo?

Grazie.

È stato utile?

Soluzione

Bene, il AccesssDecisionVoter interfaccia in realtà restituisce un int in questa situazione. Certo, il built-in implementazioni elettori sempre restituiscono solo una delle tre costanti che hai citato (e questi sono ciò che controlla i responsabili decisionali di accesso standard per), ma poi in realtà non hanno nulla in più per tornare - la RoleVoter per istanza negare l'accesso se e solo se il preside non ha il ruolo richiesto.

Dal momento che si sta utilizzando le proprie implementazioni da entrambi gli elettori e il manager decisione di accesso, sono disponibili diverse opzioni disponibili come la vedo io:

  1. Ritornare altri valori di numeri interi come una qualche forma di codice di errore; trattare ACCESS_GRANTED, ACCESS_ABSTAIN e ACCESS_DENIED come i loro valori tipici, ma trattare qualsiasi altro intero come "accesso negato" con un codice di errore. Idealmente avere una tabella di ricerca dei codici di errore disponibili -. Essenzialmente enum di un uomo povero
  2. All'interno del vostro elettore, torna Authentication come al solito, e impostare alcune proprietà accessibile pubblicamente (sia sull'oggetto elettore stesso o forse un po 'di campo statico-accessibile) con il motivo dell'errore. Nel vostro manager, se si ottiene l'accesso negato dal votante personalizzato, controllare la proprietà per ottenere i dettagli.
  3. Come sopra, impostare una proprietà errore all'interno l'elettore; ma assicurarsi che l'istanza di AccessDeniedException essere passato in uno dei vostri sottoclassi personalizzate che fornisce una buona posizione per impostare / recuperare queste informazioni.
  4. Tira un ProviderManager (o sottoclasse adatto) all'interno del tuo elettore stesso. Questo non è l'ideale in quanto presuppone la logica nel gestore decisione di accesso; ma si potrebbe o lasciare che questa bolla verso l'alto, o, se necessario, fermo all'interno del manager (una sottoclasse personalizzata sarebbe sicuramente un bene per questo) e rigenerare se l'accesso è negato in realtà (qualcosa di simile a quello che la classe lastException fa con la sua < => variabile).

Nessuno di questi bastoni fuori come la risposta, ovviamente, corretta ed elegante, ma si dovrebbe essere in grado di ottenere qualcosa di praticabile da qualunque uno è più appropriato. Poiché non v'è esplicito un sostegno nel quadro degli elettori per comunicare ragioni (si tratta di una risposta booleana dritto fondamentalmente) Non credo che si può fare molto meglio.

Altri suggerimenti

Grazie per le persone che hanno risposto.

Credo di aver trovato un modo abbastanza elegante per fare quello che volevo e ancora usare l'elettori API standard. Il 2 ° parametro al voto metodo AccessDecisionVoter è l'oggetto protetto. Posso creare un contratto tra il gestore decisione e gli elettori, che questo oggetto è di una specifica classe / interfaccia che è un involucro , attraverso il quale l'oggetto fisso originale può essere recuperata e anche informazioni aggiuntive possono essere aggiunto dagli elettori che negano l'accesso.

ho visto un modello come questo in altri framework pure. Questa soluzione presenta i seguenti vantaggi rispetto ad altre soluzioni possibili:

  • Gli elettori possono rimanere senza stato, in modo che possano essere single
  • L'interfaccia standard del AccessDecisionVoter viene utilizzato e non vengono aggiunti nuovi valori di ritorno
  • Le ulteriori informazioni vengono salvate in un oggetto che viene scartata automaticamente, perché nessuno lo usa dopo il AbstactDecisionManager 's decidere metodo, quindi non è richiesta alcuna pulizia del codice

Saluti.

Non puoi implementare AccessDecisionManager direttamente, senza usare gli elettori? È quindi possibile lanciare un AccessDeniedException con le informazioni corrette. Forse RoleVoter s non sono l'astrazione diritto di utilizzare nel tuo caso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top