【问题标题】:How to get user roles in a JSP / Servlet如何在 JSP / Servlet 中获取用户角色
【发布时间】:2008-12-05 15:14:32
【问题描述】:

有没有什么方法可以获取一个字符串[] 与用户在 JSP 或 Servlet 中的角色?

我知道 request.isUserInRole("role1") 但我也想知道用户的所有角色。

我搜索了 servlet 源,似乎这是不可能的,但这对我来说似乎很奇怪。

那么……有什么想法吗?

【问题讨论】:

    标签: java authentication jsp servlets jboss


    【解决方案1】:

    答案很混乱。

    首先你需要找出你的 webapp 中 request.getUserPrincipal() 返回的类型。

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

    假设返回 org.apache.catalina.realm.GenericPrincipal。

    然后将 getUserPrincipal() 的结果转换为该类型并使用它提供的方法。

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

    我说这会很乱。它也不是很便携。

    【讨论】:

    • 它返回类 org.jboss.security.SimplePrincipal 并且该类没有 getRoles() ......这很愚蠢......对不起,我应该提到:我正在使用 JBoss 4.2.3GA AS
    【解决方案2】:

    阅读所有可能的角色,或硬编码一个列表。然后运行 ​​isUserInRole 对其进行迭代并构建用户所在角色的列表,然后将列表转换为数组。

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

    【讨论】:

    • 是的,我可以在用户登录时执行此操作...这是一个不错的技巧。但是,这在 JBoss 中是不可能的,比如 userPrincipal.getRoles(); ?
    • 在编写 webapps 时,我总是避免使用任何特定于服务器的代码。您希望在 Tomcat 和 Resin 和 Jetty 等服务器之间保持可移植性。因此,您需要查看规范中是否有某些内容,或者从上下文中检索列表的方法。
    【解决方案3】:

    在 WebLogic 中,您可以这样做:

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

    请注意,列表中的第一个元素是用户名。

    【讨论】:

    • 我对此进行了测试,并在 Servlet 的上下文中工作。它是否也适用于 JAX-WS 上下文?
    【解决方案4】:

    在符合 JACC 的应用服务器上——理论上每个完整的 Java EE 平台实现——可以询问 Java SE Policy 以(几乎)对 Servlet 和 EJB 指定的任何类型的声明性安全约束进行可移植评估。我说几乎是因为 JACC 和 Policy#getPermissions(ProtectionDomain) 的 Javadoc 规范实际上都没有要求实现动态计算所有权限,大概是出于性能考虑,以及适应提供授权的提供者语句取决于附加上下文(远程地址、某个 HTTP GET 参数的值等)。尽管如此,getPermissions 与典型的预安装 JACC 提供程序一起使用通常应该是安全的。

    以下示例演示了 Servlet 角色分配测试:

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

    参考资料:

    【讨论】:

      猜你喜欢
      • 2014-12-30
      • 1970-01-01
      • 2015-05-14
      • 2020-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-23
      • 2013-05-21
      相关资源
      最近更新 更多