【问题标题】:Apache Shiro LDAP Configuration (2 Step Authentication)Apache Shiro LDAP 配置(两步验证)
【发布时间】:2017-02-01 07:01:54
【问题描述】:

我正在使用以下内容开发网络应用程序:

  • Apache Shiro 1.2.4
  • 雄猫 8
  • Java 8

我正在尝试通过 LDAP 领域对用户进行身份验证。

我使用以下值使用 JXplorer 测试了登录:

  • BaseND:ou=students,ou=users,o=data
  • UserDN/BindDN:cn={我的专有名称},ou=students,ou=users,o=data
  • JXplorer 还有一个我导入的证书

现在是我的问题:

我必须不是基于cn 而是基于uid 对用户进行身份验证。 但是这行不通。

我公司的 LDAP 管理员建议的工作流程:

我有一个系统用户(据我了解)应该连接到 LDAP 服务器,根据给定的 uid 搜索用户并返回该用户的 cn

在第二步中,应该可以使用他的cn 对用户进行身份验证,就像在 JXplorer 中完成(成功)一样。


我的 shiro.ini 配置对于我的测试 LDAP 看起来像这样(不是我现在尝试验证的那个)

ldapRealm = org.apache.shiro.realm.ldap.JndiLdapRealm
ldapRealm.userDnTemplate = cn={0},ou=People,dc=maxcrc,dc=com
ldapRealm.contextFactory.url = ldap://localhost:389

我现在面临的问题是,我找不到有关如何配置我的 shiro.ini 文件的信息,以从上面计算建议的工作流程。

问题 #1

可以使用标准的org.apache.shiro.realm.ldap.JndiLdapRealm(如何配置)?特别是对于证书的集成,我找不到任何合适的东西。

问题 #2

我是否需要为此“两步身份验证”创建自定义 JndiLdapRealm?这样的 Realm 是什么样子的?

【问题讨论】:

    标签: java ldap shiro


    【解决方案1】:

    我找到了一个解决方案,那就是从JndiLdapRealm重载getUserDN()方法

    现在看起来像这样:

    /**
    * Addition to standard shiro code
    * User logs in with his {@link principal} (username) but login needs to be performed with his cn instead
    * The addition is an ldap query to get the users cn from the ldap server and store it (instead of the given principal) in the return String
    * @return UserDN with user uid (cn) instead of principal (username)
    */
    @Override
    protected String getUserDn( final String principal ) throws IllegalArgumentException, IllegalStateException {
    
        if (!StringUtils.hasText(principal)) {
            throw new IllegalArgumentException("User principal cannot be null or empty for User DN construction.");
        }
        String prefix = getUserDnPrefix();
        String suffix = getUserDnSuffix();
        if (prefix == null && suffix == null) {
            log.debug("userDnTemplate property has not been configured, indicating the submitted " +
                      "AuthenticationToken's principal is the same as the User DN.  Returning the method argument " +
                      "as is.");
            return principal;
        }
    
        int prefixLength = prefix != null ? prefix.length() : 0;
        int suffixLength = suffix != null ? suffix.length() : 0;
        StringBuilder sb = new StringBuilder(prefixLength + principal.length() + suffixLength);
        if (prefixLength > 0) {
            sb.append(prefix);
        }
    
        /*############################################################################################
        * ADDITION TO STANDARD SHIRO CODE 
        * User logs in with his {@link principal} (username) but login needs to be performed with his cn instead
        *    => translate username to cn
        */
        AppSettings_Controler settings = Startup.getAppSettingsControler();
        LDAP_Manager ldap_manager = new LDAP_Manager();
        LdapContext ctx = ldap_manager.getLdapConnection();
        String user_uid = "";
    
        SearchControls constraints = new SearchControls();
        constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
        String[] attrIDs = {"cn"};
        constraints.setReturningAttributes(attrIDs);
        NamingEnumeration answer = null;
    
        try{
            answer = ctx.search(settings.get_ldap_search_dn_1(), settings.get_ldap_uname_field_name_1() + "=" + principal, constraints);
            if (answer.hasMore()) {
                Attributes attrs = ((SearchResult) answer.next()).getAttributes();
                user_uid = attrs.get("cn").toString().substring(attrIDs[0].length() + 2);
            } else {
                throw new Exception("Invalid User");
            }
        } catch (Exception ex) {
            // Error Handling & Fallback to my second LDAP-Server
            try{
                answer = ctx.search(settings.get_ldap_search_dn_2(), settings.get_ldap_uname_field_name_2() + "=" + principal, constraints);
                if (answer.hasMore()) {
                    Attributes attrs = ((SearchResult) answer.next()).getAttributes();
                    user_uid = attrs.get("cn").toString().substring(attrIDs[0].length() + 2);
                } else {
                    throw new Exception("Invalid User");
                }
            }catch (Exception exe) {
                // Error Handling
            }
        }
        try {
            ctx.close();
        } catch (NamingException ex) {
            JndiLdapRealm_custom_error_logger.error("getUserDn(); Fehler beim schließen: ", ex);
        }
        //############################################################################################
    
        //############################################################################################
        // Shiro Standard Code -> add principal to String
        //sb.append(principal);
        /*############################################################################################
    
        /*############################################################################################
        * ALTERED CODE
        * Instead -> Add user's cn to String   
        */
        sb.append(user_uid);
        //############################################################################################
    
        if (suffixLength > 0) {
            sb.append(suffix);
        }
        return sb.toString();
    }
    

    此添加执行 LDAP 查询以根据提供的用户名获取用户 uid (cn)。这样,用户只需在我的应用程序中输入其 LDAP 用户名即可登录,并遵循上述工作流程。

    如果您有任何建议或 cmets,请不要犹豫,将它们发布在这里 ;)

    【讨论】:

      猜你喜欢
      • 2018-07-31
      • 2014-07-26
      • 2015-12-24
      • 2012-03-05
      • 2017-06-28
      • 2014-12-15
      • 2023-03-06
      • 2019-06-29
      • 2016-09-28
      相关资源
      最近更新 更多