有沒有什麼方法可以通過用戶在JSP或Servlet中具有的角色來獲取String []?如何獲取JSP/Servlet中的用戶角色
我知道request.isUserInRole(「role1」),但我也想知道用戶的所有角色。
我搜索了servlet源代碼,看起來這是不可能的,但這對我來說似乎很奇怪。
那麼...有什麼想法?
有沒有什麼方法可以通過用戶在JSP或Servlet中具有的角色來獲取String []?如何獲取JSP/Servlet中的用戶角色
我知道request.isUserInRole(「role1」),但我也想知道用戶的所有角色。
我搜索了servlet源代碼,看起來這是不可能的,但這對我來說似乎很奇怪。
那麼...有什麼想法?
閱讀所有可能的角色,或硬編碼列表。然後遍歷它運行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);
答案很混亂。
首先,您需要找出request.getUserPrincipal()在您的webapp中返回的類型。
System.out.println("type = " + request.getUserPrincipal().getClass());
比方說,返回org.apache.catalina.realm.GenericPrincipal。
然後將getUserPrincipal()的結果轉換爲該類型並使用它提供的方法。
我說這會變得混亂。它也不是很便攜。
它返回類org.jboss.security.SimplePrincipal,並且該類沒有getRoles()...這是非常愚蠢的... 對不起,我應該提到:我使用JBoss 4.2.3GA AS – AlfaTeK 2008-12-05 15:47:10
在WebLogic中,你可以用做:
import weblogic.security.Security;
import weblogic.security.SubjectUtils;
...
private List<String> getUserRoles() {
return Arrays.asList(SubjectUtils.getPrincipalNames(Security.getCurrentSubject()).split("/"));
}
注意的是,名單上的第一個元素是用戶名。
在JACC兼容的應用程序服務器上 - 理論上每個完整的Java EE平臺實現 - Java SE Policy
都可以用於評估由Servlet和EJB指定的任何類型的聲明性安全約束。
下面的例子演示了角色分配測試:
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() {
}
}
參考文獻:
是的,我可以在用戶進行登錄時執行此操作......這是一個很好的入侵。 但仍然,這是不可能在JBoss做userPrincipal.getRoles(); ? – AlfaTeK 2008-12-05 15:56:09
當談到編寫webapps時,我總是避免使用任何特定於服務器的代碼。您希望保持Tomcat,Resin和Jetty等服務器的可移植性。因此,您需要查看規範中是否存在某些內容或從上下文中檢索列表的方法。 – Josh 2008-12-16 23:58:10