简体   繁体   English

如何在JSP / Servlet中获取用户角色

[英]How to get user roles in a JSP / Servlet

Is there any way to get a String[] with the roles a user has in the JSP or Servlet? 有没有办法获得一个String []与用户在JSP或Servlet中的角色?

I know about request.isUserInRole("role1") but I also want to know all the roles of the user. 我知道request.isUserInRole(“role1”),但我也想知道用户的所有角色。

I searched the servlet source and it seems this is not possible, but this seems odd to me. 我搜索了servlet源代码,看起来这是不可能的,但这对我来说似乎很奇怪。

So... any ideas? 所以...任何想法?

The answer is messy. 答案很乱。

First you need to find out what type request.getUserPrincipal() returns in your webapp. 首先,您需要找出request.getUserPrincipal()在您的webapp中返回的类型。

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

Let's say that returns org.apache.catalina.realm.GenericPrincipal. 假设返回org.apache.catalina.realm.GenericPrincipal。

Then cast the result of getUserPrincipal() to that type and use the methods it provides. 然后将getUserPrincipal()的结果转换为该类型并使用它提供的方法。

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

I said it was going to be messy. 我说它会变得凌乱。 It's not very portable either. 它也不是很便携。

Read in all the possible roles, or hardcode a list. 读入所有可能的角色,或硬编码列表。 Then iterate over it running the isUserInRole and build a list of roles the user is in and then convert the list to an array. 然后迭代它运行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);

In WebLogic you can do it with: 在WebLogic中,您可以使用:

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

Note that the first element on the list is the user name. 请注意,列表中的第一个元素是用户名。

On JACC-compliant application servers -- in theory every Full Java EE Platform implementation -- the Java SE Policy can be interrogated for (almost) portable evaluation of any type of declarative security constraint specified by Servlet and EJB. 在符合JACC的应用程序服务器上 - 理论上每个完整的Java EE平台实现 - 可以查询Java SE Policy以便(几乎)可移植地评估Servlet和EJB指定的任何类型的声明性安全约束。 I say almost because neither JACC nor the Javadoc spec of Policy#getPermissions(ProtectionDomain) actually requires that the implementation compute all permissions on the fly, presumably due to performance considerations, as well as to accommodate for providers whose rendering of authorization statements depends on additional context (remote address, value of a certain HTTP GET parameter, etc.). 我说几乎是因为JACC和Policy#getPermissions(ProtectionDomain)的Javadoc规范实际上都不需要实时计算所有权限,可能是出于性能考虑,以及适应授权语句的呈现依赖于附加的提供者上下文(远程地址,某个HTTP GET参数的值等)。 Nonetheless, getPermissions should normally be safe to use with the typical pre-installed JACC provider. 尽管如此, getPermissions通常可以安全地与典型的预安装JACC提供程序一起使用。

The following example demonstrates Servlet role assignment testing: 以下示例演示了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() {
    }

}

References: 参考文献:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM