2014-06-05 167 views
7

請幫我解決以下情況嗎?Shiro LDAP授權配置

背景資料:

[主要]

contextFactory = org.apache.shiro.realm.ldap.JndiLdapContextFactory 
contextFactory.url = ldaps://<SERVER>:636 
contextFactory.systemUsername = <USERNAME>@<COMPANY> 
contextFactory.systemPassword = <PASSWORD> 
contextFactory.environment[java.naming.security.protocol] = ssl 

realm = org.apache.shiro.realm.activedirectory.ActiveDirectoryRealm 
realm.ldapContextFactory = $contextFactory 
realm.searchBase = "OU=<APPDIR>,DC=<COMPANY>,DC=lcl" 
realm.groupRolesMap = "CN=<ROLE>,OU=<APPDIR>,DC=<COMPANY>,DC=lcl":"Admin" 

[角色]

# 'Admin' role has permissions * 
Admin = * 

目標

  • 基於currentUser的memberOf字段的授權映射。

問題

  • currentUser.hasRole( 「管理」)總是返回false。

問題

  • 是上述shiro.ini是否正確?
  • 我該如何解決這個問題?

回答

1

我遇到了類似的問題,使用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屬性
  • 如何變化四郎搜索用戶

我去了第二個解決方案。更改搜索查詢比應該更難:您必須自定義queryForAuthorizationInfogetRoleNamesForUser(因爲它的私有方法)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"