我遇到了類似的問題,使用Shiro 1.2.4。你的Shiro配置可能是好的,問題在於ActiveDirectory配置。
在我的設置中,某些用戶擁有userPrincipalName屬性集,而其他用戶則沒有。例如,您可以使用Sysinternals Active Directory Explorer檢查您的AD服務器。
此屬性是Shiro用來搜索特定用戶的屬性,然後它查找在成員屬性中定義的組。
在ActiveDirectoryRealm.java源代碼看看,方法Set<String> getRoleNamesForUser(String username, LdapContext ldapContext)
所使用的精確查詢
String searchFilter = "(&(objectClass=*)(userPrincipalName={0}))";
所以,你有兩種解決方法:對每個用戶
- 設置的UserPrincipalName屬性
- 如何變化四郎搜索用戶
我去了第二個解決方案。更改搜索查詢比應該更難:您必須自定義queryForAuthorizationInfo
和getRoleNamesForUser
(因爲它的私有方法)ActiveDirectoryRealm
類。這是我做的:
public class CustomActiveDirectoryRealm extends ActiveDirectoryRealm {
@Override
protected AuthorizationInfo queryForAuthorizationInfo(PrincipalCollection principals, LdapContextFactory ldapContextFactory) throws NamingException {
String username = (String) getAvailablePrincipal(principals);
// Perform context search
LdapContext ldapContext = ldapContextFactory.getSystemLdapContext();
Set<String> roleNames = null;
try {
roleNames = getRoleNamesForUser(username, ldapContext);
} finally {
LdapUtils.closeContext(ldapContext);
}
return buildAuthorizationInfo(roleNames);
}
// Customize your search query here
private static final String USER_SEARCH_FILTER = "(&(objectClass=*)(sn={0}))";
private Set<String> getRoleNamesForUser(String username, LdapContext ldapContext) throws NamingException {
Set<String> roleNames;
roleNames = new LinkedHashSet<String>();
SearchControls searchCtls = new SearchControls();
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String userPrincipalName = username.replace("acegas\\", "");
if (principalSuffix != null) {
userPrincipalName += principalSuffix;
}
Object[] searchArguments = new Object[]{userPrincipalName};
NamingEnumeration answer = ldapContext.search(searchBase, USER_SEARCH_FILTER, searchArguments, searchCtls);
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult) answer.next();
Attributes attrs = sr.getAttributes();
if (attrs != null) {
NamingEnumeration ae = attrs.getAll();
while (ae.hasMore()) {
Attribute attr = (Attribute) ae.next();
if (attr.getID().equals("memberOf")) {
Collection<String> groupNames = LdapUtils.getAllAttributeValues(attr);
Collection<String> rolesForGroups = getRoleNamesForGroups(groupNames);
roleNames.addAll(rolesForGroups);
}
}
}
}
return roleNames;
}
}
然後當然使用這個類的領域中shiro.ini
[main]
realm = your.package.CustomActiveDirectoryRealm
realm.ldapContextFactory = $contextFactory
realm.searchBase = "OU=<APPDIR>,DC=<COMPANY>,DC=lcl"
realm.groupRolesMap = "CN=<ROLE>,OU=<APPDIR>,DC=<COMPANY>,DC=lcl":"Admin"