Shiro LDAP授权配置

use*_*448 8 java authentication ldap vaadin shiro

你能帮我解决下列情况吗?

背景资料:

  • 我正在使用Vaadin框架.
  • 我正在使用Java安全框架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"
Run Code Online (Sandbox Code Playgroud)

[作用]

 # 'Admin' role has permissions * 
 Admin = * 
Run Code Online (Sandbox Code Playgroud)

目标

  • 基于currentUser的memberOf字段的授权映射.

问题

  • currentUser.hasRole("Admin")始终返回false.

问题

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

Ale*_*gna 1

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

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

所以你有两个解决方案:

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

我选择了第二种解决方案。更改搜索查询比应有的困难:您必须自定义类的queryForAuthorizationInfoand 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后当然在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"
Run Code Online (Sandbox Code Playgroud)