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

Java 如何在JSP/Servlet中获取用户角色,java,authentication,jsp,servlets,jboss,Java,Authentication,Jsp,Servlets,Jboss,有没有办法获得一个字符串[],其中包含用户在JSP或Servlet中的角色 我知道request.isUserInRole(“role1”),但我也想知道用户的所有角色 我搜索了servlet源代码,似乎这是不可能的,但我觉得这很奇怪 所以。。。有什么想法吗?答案很混乱 首先,您需要找出request.getUserPrincipal()在您的webapp中返回的类型 System.out.println("type = " + request.getUserPrincipal().ge

有没有办法获得一个字符串[],其中包含用户在JSP或Servlet中的角色

我知道request.isUserInRole(“role1”),但我也想知道用户的所有角色

我搜索了servlet源代码,似乎这是不可能的,但我觉得这很奇怪

所以。。。有什么想法吗?

答案很混乱

首先,您需要找出request.getUserPrincipal()在您的webapp中返回的类型

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

我说会很乱的。它也不是很便于携带。

读入所有可能的角色,或者硬编码列表。然后运行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);

在WebLogic中,您可以使用:

import weblogic.security.Security;
import weblogic.security.SubjectUtils;
...
private List<String> getUserRoles()  {
    return Arrays.asList(SubjectUtils.getPrincipalNames(Security.getCurrentSubject()).split("/"));
}
导入weblogic.security.security;
导入weblogic.security.substructils;
...
私有列表getUserRoles(){
返回Arrays.asList(subarchitecture.getPrincipalNames(Security.getCurrentSubject()).split(“/”);
}

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

在符合JACC的应用服务器上——理论上,每个完整的Java EE平台实现——可以查询Java SE
策略,以便(几乎)可移植地评估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() {
    }

}
package.com.example;
导入java.security.CodeSource;
导入java.security.Permission;
导入java.security.PermissionCollection;
导入java.security.Policy;
导入java.security.Principal;
导入java.security.ProtectionDomain;
导入java.security.cert.Certificate;
导入java.util.Collections;
导入java.util.Enumeration;
导入java.util.HashSet;
导入java.util.Set;
导入javax.security.auth.Subject;
导入javax.security.jacc.PolicyContext;
导入javax.security.jacc.PolicyContextException;
导入javax.security.jacc.WebRoleRefPermission;
公共最终类Util{
private static final Set NO_ROLES=Collections.emptySet();
私有静态最终权限DUMMY\u WEB\u ROLE\u REF\u PERM=new-WebRoleRefPermission(“,”DUMMY”);
/**
*检索已映射到的{@code Principal}的声明的Servlet安全角色
*当前经过身份验证的{@code Subject},可以选择限制在Servlet的范围内
*由{@code servletName}引用。
* 
*@param servletName
*作用域;{@code null}表示Servlet上下文范围的匹配。
*@返回角色;空{@code Set}iff:
*
    *
  • 远程用户未经身份验证
  • *
  • 远程用户尚未与搜索中声明的任何角色关联 *范围
  • *
  • 未在Servlet调用上下文中调用该方法
  • *
*/ 公共静态集getCallerWebRoles(字符串servletName){ //获取当前主题 Subject=getSubject(); if(subject==null){ //未经认证 不返回任何角色; } Set principals=subject.getPrincipals(); if(principals.isEmpty()){ //未经认证? 不返回任何角色; } //构造一个用于查询策略的域;代码源应该无关紧要 //关注JACC权限 ProtectionDomain域=新的ProtectionDomain(新代码源(null,(证书[])null),null,null, principals.toArray(新的Principal[principals.size()]); //获取授予这些主体的所有权限 PermissionCollection pc=Policy.getPolicy().getPermissions(域); //导致集合中WebRoleRefPermissions(如果有)的解析(如果仍然未解析) pc.implies(虚拟WEB角色参考PERM); 枚举e=pc.elements(); 如果(!e.hasMoreElements()){ //没有授予,因此没有角色 不返回任何角色; } 设置角色名称=无角色; //迭代集合并消除重复项 而(e.hasMoreElements()){ 权限p=e.nextElement(); //仅对Servlet容器安全角色(-ref)权限感兴趣 if(WebRoleRefPermission的p实例){ 字符串candidateRoleName=p.getActions(); //-忽略“任何经过身份验证的用户”角色(仅当您的 //应用程序实际声明了一个名为“**”的角色) //-还限制由servletName标识的Servlet的范围 //参数,除非为null 如果(!“**”.equals(candidateRoleName)&((servletName==null)| | servletName.equals(p.getName())) &&((roleNames==无角色)| |!roleNames.contains(candidateRoleName))){ 如果(角色名称==无角色){ roleNames=新的HashSet(); } 添加(候选名称); } } } 返回角色名称; } 私有静态主题getSubject(){ 返回getFromJaccPolicyContext(“javax.security.auth.Subject.con