Shiro LDAP 授权配置

Posted

技术标签:

【中文标题】Shiro LDAP 授权配置【英文标题】:Shiro LDAP Authorization config 【发布时间】:2014-07-26 13:49:21 【问题描述】:

您能帮我解决以下情况吗?

背景信息:

我正在使用Vaadin framework。 我正在使用Java security framework Shiro 我正在使用 ssl。 身份验证有效。 用户名语法 = pietj@.lcl , jank@.lcl memberOf 字段被用作角色。 shiro.ini

[主要]

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("Admin") 总是返回 false。

问题

上面的 shiro.ini 是否正确? 我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

我在使用 Shiro 1.2.4 时遇到了类似的问题。您的 Shiro 配置可能没问题,问题在于 ActiveDirectory 配置。

在我的设置中,一些用户设置了 userPrincipalName 属性,而其他用户则没有。例如,您可以使用Sysinternals Active Directory Explorer 检查您的 AD 服务器。 此属性是 Shiro 用于搜索特定用户的属性,然后它会查找在 memberOf 属性中定义的组。 看看ActiveDirectoryRealm.java源码,方法Set&lt;String&gt; getRoleNamesForUser(String username, LdapContext ldapContext)使用的具体查询是String searchFilter = "(&amp;(objectClass=*)(userPrincipalName=0))";

所以你有两个解决方案:

为每个用户设置 userPrincipalName 属性 更改 Shiro 搜索用户的方式

我选择了第二种解决方案。更改搜索查询比应有的更难:您必须自定义 ActiveDirectoryRealm 类的 queryForAuthorizationInfogetRoleNamesForUser(因为它是私有的)方法。我就是这样做的:

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 中使用这个类作为 Realm

[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"

【讨论】:

以上是关于Shiro LDAP 授权配置的主要内容,如果未能解决你的问题,请参考以下文章

如何使用带有 LDAP 身份验证的 Apache Shiro 添加角色授权

Apache Shiro - 用于身份验证和属性的 LDAP/用于授权的 Ini

在 Apache Shiro 中使用 ActiveDirectoryRealm 时如何搜索 ldap 字段?

源码分析 shiro注解授权

SpringBoot整合Shiro 四:认证+授权

Shiro学习——认证与授权(ini文件配置与数据库配置方式)