2016-09-23 13 views
1

私は、次を使用して、webアプリケーションに取り組んでいます:Apacheの史郎LDAPの設定(2ステップ認証)

  • アパッチ史郎1.2.4
  • Tomcatの8
  • のJava 8

私はLDAPレルム経由でユーザーを認証しようとしています。 OU、CN = {私の識別名}:

  • BaseND:OU =学生、OU =ユーザー、O =データ
  • ユーザーDN/BINDDN

    は、私は次の値を使用してJXplorerのでログインをテストしました=学生、OU =ユーザー、データ
  • JXplorerのも、私は私の問題に今

をインポートした証明書を持っている=○:

cnではなく、uidに基づいてユーザーを認証する必要があります。 しかし、これは動作しません。私の会社では、LDAP管理者によって提案された

ワークフロー:私は、(私の知る限り理解されるような)LDAP-Serverに接続する必要があり、システムの利用者を持つ

uidを与えられたとに基づいてユーザを検索しますそのユーザーのcnを返します。

2番目のステップでは、彼のcnをJXplorerのdone(成功)と同様に認証することができます。


マイshiro.ini設定は私のテストLDAP(私は今に対して認証しようとしていない1)

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

私は、この「2段階認証」用のカスタムJndiLdapRealmを作成する必要がありますか、どのようなレルムようになりますか?

答えて

1

は私がsolutiuonを発見し、それはそれは次のようになります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(); 
} 

このほかには、(CN)をユーザーのUIDを取得するためのLDAP-クエリを行いますn提供されたユーザー名に基づいています。こうすることで、ログインは自分のアプリケーションで自分のLDAP-Usernameを入力するだけで動作し、上記のワークフローに従います。

ここに投稿することをお待ちしております(お気軽にお寄せください)