2008-11-12 13 views
4

Je donne aux utilisateurs une URL spéciale avec une clé d'accès. les utilisateurs accédant à la page publique via cette URL spéciale devraient être en mesure de voir des données supplémentaires par rapport au simple utilisateur anonyme.Sécurité Acegi: Comment ajouter un autre GrantedAuthority à l'authentification à l'utilisateur anonyme

je veux donner un rôle supplémentaire à l'utilisateur anonyme en fonction des paramètres fournis à la demande afin que je puisse faire quelque chose comme ça dans mon modèle:

<@sec.authorize ifAnyGranted="ROLE_ADMIN, ROLE_USER, ROLE_INVITED_VISITOR"> 
...some additional stuff for invited user to see 
</@sec.authorize> 

actuellement je suis mise en œuvre OncePerRequestfilter de printemps:

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { 
    if (null != request.getParameter("accessKey")) { 
     if(isValid(request.getParameter("accessKey"))) { 
      Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 
      //how do i add additional roles to authenticated (potentially anonymous) user? 
     } 
    } 
} 

Répondre

6

Pourquoi ne pas simplement créer une classe wrapper qui délègue à l'original, mais ajoute sur un couple de GrantedAuthorities supplémentaires:

public class AuthenticationWrapper implements Authentication 
{ 
    private Authentication original; 
    private GrantedAuthority[] extraRoles; 

    public AuthenticationWrapper(Authentication original, GrantedAuthority[] extraRoles) 
    { 
     this.original = original; 
     this.extraRoles = extraRoles; 
    } 

    public GrantedAuthority[] getAuthorities() 
    { 
     GrantedAuthority[] originalRoles = original.getAuthorities(); 
     GrantedAuthority[] roles = new GrantedAuthority[originalRoles.length + extraRoles.length]; 
     System.arraycopy(originalRoles, 0, roles, 0, originalRoles.length); 
     System.arraycopy(extraRoles, 0, roles, originalRoles.length, extraRoles.length); 
     return roles; 
    } 

    public String getName() { return original.getName(); } 
    public Object getCredentials() { return original.getCredentials(); } 
    public Object getDetails() { return original.getDetails(); } 
    public Object getPrincipal() { return original.getPrincipal(); } 
    public boolean isAuthenticated() { return original.isAuthenticated(); } 
    public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException 
    { 
     original.setAuthenticated(isAuthenticated); 
    } 
} 

et faites ceci dans votre filtre:

Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 
GrantedAuthority extraRoles = new GrantedAuthority[2]; 
extraRoles[0] = new GrantedAuthorityImpl("Role X"); 
extraRoles[1] = new GrantedAuthorityImpl("Role Y"); 
AuthenticationWrapper wrapper = new AuthenticationWrapper(auth, extraRoles); 
SecurityContextHolder.getContext().setAuthentication(wrapper); 

L'authentification est maintenant remplacée par votre version avec les rôles supplémentaires. NB Vous devrez peut-être gérer le cas où l'authentification n'a pas encore été authentifiée et donc son getAuthorities() retourne null. (L'implémentation de wrapper suppose actuellement qu'elle obtiendra toujours un tableau non nul à partir de son authentification encapsulée)

+0

nice one! Je l'ai moi-même résolu en créant une nouvelle AnonymousAuthenticationToken avec des rôles supplémentaires, mais c'est beaucoup plus élégant. Merci – miceuz