2008-12-05 42 views
11

¿Hay alguna forma de obtener un String [] con los roles que un usuario tiene en JSP o Servlet?Cómo obtener roles de usuario en un JSP/Servlet

Sé de request.isUserInRole ("role1") pero también quiero conocer todos los roles del usuario.

He buscado la fuente de servlet y parece que esto no es posible, pero esto me parece extraño.

Entonces ... alguna idea?

Respuesta

6

Lea todas las funciones posibles o codifique una lista. A continuación, repítalo ejecutando isUserInRole y elabore una lista de las funciones en las que se encuentra el usuario y luego convierta la lista en una matriz.

String[] allRoles = {"1","2","3"}; 
HttpServletRequest request = ... (or from method argument) 
List userRoles = new ArrayList(allRoles.length); 
for(String role : allRoles) { 
if(request.isUserInRole(role)) { 
    userRoles.add(role); 
} 
} 

// I forgot the exact syntax for list.toArray so this is prob wrong here 
return userRoles.toArray(String[].class); 
+0

Sí, puedo hacer esto cuando el usuario inicia sesión ... Es un buen truco. Pero aún así, ¿esto es imposible de hacer en JBoss como userPrincipal.getRoles(); ? – AlfaTeK

+0

Cuando se trata de escribir webapps, siempre evito cualquiera de los códigos específicos del servidor. Desea mantener la portabilidad en servidores como Tomcat, Resin y Jetty. Entonces, necesitaría ver si hay algo en la especificación, o una forma de recuperar la lista del contexto. – Josh

10

La respuesta es desordenada.

Primero debe averiguar qué tipo request.getUserPrincipal() devuelve en su aplicación web.

System.out.println("type = " + request.getUserPrincipal().getClass()); 

Digamos que devuelve org.apache.catalina.realm.GenericPrincipal.

Luego eche el resultado de getUserPrincipal() a ese tipo y use los métodos que proporciona.

final Principal userPrincipal = request.getUserPrincipal(); 
    GenericPrincipal genericPrincipal = (GenericPrincipal) userPrincipal; 
    final String[] roles = genericPrincipal.getRoles(); 

Dije que iba a ser un desastre. Tampoco es muy portátil.

+1

Devuelve la clase org.jboss.security.SimplePrincipal y esa clase no tiene getRoles() ... que es muy estúpido ... Lo siento, debería haber mencionado: Estoy usando JBoss 4.2.3GA AS – AlfaTeK

4

En WebLogic se puede hacer con:

import weblogic.security.Security; 
import weblogic.security.SubjectUtils; 
... 
private List<String> getUserRoles() { 
    return Arrays.asList(SubjectUtils.getPrincipalNames(Security.getCurrentSubject()).split("/")); 
} 

Tenga en cuenta que el primer elemento de la lista es el nombre de usuario.

+0

Probé esto y en trabajos en el contexto de un Servlet. ¿Funciona también en el contexto de JAX-WS? – Abbadon

0

En los servidores de aplicaciones compatibles con JACC, en teoría, todas las implementaciones de la plataforma Java EE completa, se puede interrogar a Java SE Policy para evaluar cualquier tipo de restricción de seguridad declarativa especificada por Servlet y EJB.

El siguiente ejemplo demuestra la prueba de asignación de funciones:

package com.example; 

import java.security.CodeSource; 
import java.security.Permission; 
import java.security.PermissionCollection; 
import java.security.Policy; 
import java.security.Principal; 
import java.security.ProtectionDomain; 
import java.security.cert.Certificate; 
import java.util.Collections; 
import java.util.Enumeration; 
import java.util.HashSet; 
import java.util.Set; 

import javax.security.auth.Subject; 
import javax.security.jacc.PolicyContext; 
import javax.security.jacc.PolicyContextException; 
import javax.security.jacc.WebRoleRefPermission; 

public final class Util { 


    private static final Set<String> NO_ROLES = Collections.emptySet(); 
    private static final Permission DUMMY_WEB_ROLE_REF_PERM = new WebRoleRefPermission("", "dummy"); 

    /** 
    * Retrieves the declared Servlet security roles that have been mapped to the {@code Principal}s of 
    * the currently authenticated {@code Subject}, optionally limited to the scope of the Servlet 
    * referenced by {@code servletName}. 
    * 
    * @param servletName 
    *   The scope; {@code null} indicates Servlet-context-wide matching. 
    * @return the roles; empty {@code Set} iff: 
    *   <ul> 
    *   <li>the remote user is unauthenticated</li> 
    *   <li>the remote user has not been associated with any roles declared within the search 
    *   scope</li> 
    *   <li>the method has not been called within a Servlet invocation context</li> 
    *   </ul> 
    */ 
    public static Set<String> getCallerWebRoles(String servletName) { 
     // get current subject 
     Subject subject = getSubject(); 
     if (subject == null) { 
      // unauthenticated 
      return NO_ROLES; 
     } 
     Set<Principal> principals = subject.getPrincipals(); 
     if (principals.isEmpty()) { 
      // unauthenticated? 
      return NO_ROLES; 
     } 
     // construct a domain for querying the policy; the code source shouldn't matter, as far as 
     // JACC permissions are concerned 
     ProtectionDomain domain = new ProtectionDomain(new CodeSource(null, (Certificate[]) null), null, null, 
       principals.toArray(new Principal[principals.size()])); 
     // get all permissions accorded to those principals 
     PermissionCollection pc = Policy.getPolicy().getPermissions(domain); 
     // cause resolution of WebRoleRefPermissions, if any, in the collection, if still unresolved 
     pc.implies(DUMMY_WEB_ROLE_REF_PERM); 
     Enumeration<Permission> e = pc.elements(); 
     if (!e.hasMoreElements()) { 
      // nothing granted, hence no roles 
      return NO_ROLES; 
     } 
     Set<String> roleNames = NO_ROLES; 
     // iterate over the collection and eliminate duplicates 
     while (e.hasMoreElements()) { 
      Permission p = e.nextElement(); 
      // only interested in Servlet container security-role(-ref) permissions 
      if (p instanceof WebRoleRefPermission) { 
       String candidateRoleName = p.getActions(); 
       // - ignore the "any-authenticated-user" role (only collect it if your 
       // application has actually declared a role named "**") 
       // - also restrict to the scope of the Servlet identified by the servletName 
       // argument, unless null 
       if (!"**".equals(candidateRoleName) && ((servletName == null) || servletName.equals(p.getName())) 
         && ((roleNames == NO_ROLES) || !roleNames.contains(candidateRoleName))) { 
        if (roleNames == NO_ROLES) { 
         roleNames = new HashSet<>(); 
        } 
        roleNames.add(candidateRoleName); 
       } 
      } 
     } 
     return roleNames; 
    } 

    private static Subject getSubject() { 
     return getFromJaccPolicyContext("javax.security.auth.Subject.container"); 
    } 

    @SuppressWarnings("unchecked") 
    private static <T> T getFromJaccPolicyContext(String key) { 
     try { 
      return (T) PolicyContext.getContext(key); 
     } 
     catch (PolicyContextException | IllegalArgumentException e) { 
      return null; 
     } 
    } 

    private Util() { 
    } 

} 

Referencias:

Cuestiones relacionadas