Comment lancer une exception d'information de AccessDecisionManager qui utilise les électeurs

StackOverflow https://stackoverflow.com/questions/510846

Question

J'ai la situation suivante: le mécanisme d'autorisation de mon application est exécutée à l'aide de la sécurité de printemps. Les outils de classe centrale AccessDecisionManager et utilise les électeurs (dont chacun met en œuvre AccessDecisionVoter ) pour décider d'accorder l'accès à une méthode ou non. L'algorithme qui cadre les votes est la coutume:

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");
        }               
    }

}

À refuser un accès à une méthode, le client de l'application est intéressé à obtenir une exception informative qui spécifie exactement pourquoi l'accès est refusé. Cela implique le passage des informations des électeurs au gestionnaire de décision. Malheureusement, la seule information la norme AccessDecisionVoter passe au gestionnaire de décision est l'une des valeurs de retour possibles ( ACCESS_GRANTED , ACCESS_ABSTAIN ou ACCESS_DENIED ).

Quelle est la meilleure façon de le faire?

Merci.

Était-ce utile?

La solution

Eh bien, l'interface retourne en fait un AccesssDecisionVoter dans cette situation int. Certes, intégré dans les implémentations des électeurs reviennent toujours que l'une des trois constantes que vous avez mentionnées (et ce sont ce que les gestionnaires de décision d'accès standard vérifier), mais ils n'ont pas vraiment rien de plus pour revenir - la RoleVoter pour par exemple interdira l'accès si et seulement si le principal n'a pas le rôle nécessaire.

Puisque vous utilisez vos propres implémentations deux des électeurs et le gestionnaire de décision d'accès, vous disposez de plusieurs options disponibles comme je le vois:

  1. Retour d'autres valeurs d'entiers comme une certaine forme de code d'erreur; traiter ACCESS_GRANTED, et ACCESS_ABSTAIN comme leurs valeurs ACCESS_DENIED typiques, mais traiter tout autre entier comme « accès refusé » avec un code d'erreur. Idéalement avoir une table de correspondance des codes d'erreur -. essentiellement ENUM du pauvre homme
  2. Au sein de votre électeur, comme d'habitude retour Authentication, et mis une propriété accessible au public (soit sur l'objet lui-même électeur ou peut-être un domaine statiquement accessible) avec la raison d'erreur. Dans votre gestionnaire, si vous obtenez un accès refusé de votre électeur personnalisée, vérifiez la propriété pour obtenir les détails.
  3. Comme ci-dessus, définir une propriété d'erreur au sein de l'électeur; mais veiller à ce que l'instance de se passer dans AccessDeniedException est l'un de vos sous-classes personnalisées qui offre un bon position pour définir / récupérer ces informations.
  4. Jetez un ProviderManager (ou sous-classe appropriée) à partir de votre électeur lui-même. Ce n'est pas idéal car il suppose la logique dans le gestionnaire de décision d'accès; mais vous pouvez soit laisser directement cette bulle, ou si nécessaire, il capture dans le gestionnaire (une sous-classe personnalisée serait certainement bon pour cela) et réémettre si l'accès est vraiment refusé (quelque chose de semblable à ce que la classe fait avec lastException son < => variable).

Aucune de ces bâtons comme la réponse correcte évidemment et élégante, mais vous devriez être en mesure d'obtenir quelque chose de réalisable selon est le plus approprié. Comme il n'y a pas de explicite soutien dans le cadre des électeurs pour des raisons de communication (il est une réponse booléenne droit fondamental) Je ne pense pas que vous pouvez faire beaucoup mieux.

Autres conseils

Merci pour les personnes qui ont répondu.

Je pense que je l'ai trouvé un moyen assez élégant pour faire ce que je voulais et toujours utiliser l'API standard électorale. Le 2ème paramètre à vote méthode de AccessDecisionVoter est l'objet sécurisé. Je peux créer un contrat entre le gestionnaire de décision et les électeurs, que cet objet est d'une classe / interface spécifique qui est un wrapper , à travers lequel l'objet sécurisé d'origine peut être tiré par les cheveux ainsi que des informations supplémentaires peuvent être ajoutée par les électeurs qui refusent l'accès.

J'ai vu un modèle comme celui-ci dans d'autres cadres aussi bien. Cette solution présente les avantages suivants par rapport aux autres solutions possibles:

  • Les électeurs peuvent rester sans état, de sorte qu'ils peuvent être singletons
  • L'interface standard du AccessDecisionVoter est utilisé et aucune nouvelle valeurs de retour sont ajoutés
  • Les informations supplémentaires sont enregistrées dans un objet qui est automatiquement rejeté parce que personne ne l'utilise après la balise AbstactDecisionManager s DECiDE méthode, donc pas de code de nettoyage est nécessaire

Vive.

Tu ne peux pas mettre en œuvre directement AccessDecisionManager, sans utiliser les électeurs? Vous pouvez ensuite jeter un avec les informations AccessDeniedException correcte. Peut-être ne sont pas s RoleVoter l'abstraction droit d'utiliser dans votre cas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top