2008-12-05 12 views
11

Gibt es eine Möglichkeit, einen String [] mit den Rollen eines Benutzers in der JSP oder im Servlet abzurufen?Wie erhält man Benutzerrollen in einem JSP/Servlet?

Ich weiß über request.isUserInRole ("role1"), aber ich möchte auch alle Rollen des Benutzers kennen.

Ich suchte die Servlet-Quelle und es scheint, dass dies nicht möglich ist, aber das scheint mir seltsam.

Also ... irgendwelche Ideen?

Antwort

6

Alle möglichen Rollen einlesen oder eine Liste hartcodieren. Führen Sie dann eine iteration mit dem Befehl isUserInRole durch, erstellen Sie eine Liste der Rollen, in denen sich der Benutzer befindet, und konvertieren Sie die Liste in ein Array.

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

Ja, ich kann das tun, wenn der Benutzer die Anmeldung macht ... Das ist ein netter Hack. Aber immer noch, ist dies in JBoss wie userPrincipal.getRoles(); ? – AlfaTeK

+0

Wenn es darum geht, Webapps zu schreiben, vermeide ich immer den serverspezifischen Code. Sie möchten die Portabilität zwischen Servern wie Tomcat und Resin and Jetty beibehalten. Sie müssten also sehen, ob in der Spezifikation etwas enthalten ist oder wie Sie die Liste aus dem Kontext abrufen können. – Josh

10

Die Antwort ist chaotisch.

Zuerst müssen Sie herausfinden, welchen Typ request.getUserPrincipal() in Ihrer Webapp zurückgibt.

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

Lassen Sie uns sagen, dass org.apache.catalina.realm.GenericPrincipal zurückgibt.

Dann werfen Sie das Ergebnis von getUserPrincipal() auf diesen Typ und verwenden Sie die bereitgestellten Methoden.

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

Ich sagte, es würde chaotisch sein. Es ist auch nicht sehr tragbar.

+1

Es gibt Klasse org.jboss.security.SimplePrincipal zurück und diese Klasse hat keine getRoles() ... was sehr dumm ist ... Entschuldigung, ich hätte erwähnen sollen: Ich benutze JBoss 4.2.3GA AS – AlfaTeK

4

In WebLogic können Sie es mit:

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

Beachten Sie, dass das erste Element in der Liste die Namen Benutzer.

+0

Ich habe dies und in Arbeiten im Zusammenhang mit einem Servlet getestet. Funktioniert es auch im Zusammenhang mit JAX-WS? – Abbadon

0

Auf JACC-konformen Anwendungsservern - theoretisch kann jede vollständige Java EE Platform-Implementierung - das Java SE Policy zur Bewertung jeglicher Art deklarativer Sicherheitsbeschränkungen, die von Servlet und EJB spezifiziert werden, abgefragt werden.

Das folgende Beispiel zeigt Rollenzuweisung Prüfung:

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() { 
    } 

} 

Referenzen: