4

LDAP 認証を使用する Java EE Web アプリケーションがあります。Spring セキュリティを使用して、次のコードで LDAP に接続します。

<bean id="ldapContextSource" class="com.myapp.security.authentication.MySecurityContextSource">
    <constructor-arg index="0" value="${ldap.url}" />
    <constructor-arg index="1" ref="userConnexion" />
</bean>

<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="ldapAuthProvider" />
</security:authentication-manager>

<bean id="userConnexion" class="com.myapp.util.security.WebsphereCredentials">
    <constructor-arg value="${ldap.authJndiAlias}" />
</bean>

<bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
    <constructor-arg>
        <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
            <constructor-arg ref="ldapContextSource" />
            <property name="userSearch" ref="userSearch" />
        </bean>
    </constructor-arg>
    <constructor-arg>
        <bean class="com.myapp.security.authentication.MyAuthoritiesPopulator" >
            <property name="userService" ref="userService" />
        </bean>
    </constructor-arg>
    <property name="userDetailsContextMapper" ref="myUserDetailsContextMapper"/>
    <property name="hideUserNotFoundExceptions" value="false" />
</bean>

実際、私の Beanは、この応答のようにWebsphereCredentialsWebSphere プライベート クラスを使用します: Websphere 6.1 にデプロイされた EJB から認証エイリアスにアクセスする方法WSMappingCallbackHandlerFactory

Websphere の公式ドキュメントで確認できます: http://pic.dhe.ibm.com/infocenter/wasinfo/v6r1/index.jsp?topic=%2Fcom.ibm.websphere.express.doc%2Finfo%2Fexp%2Fae %2Frsec_pluginj2c.html

しかし、私はそれを望んでいません:

  1. 私のアプリケーションは、WebSphere インスタンスのすべての JAAS ログインにアクセスできると思います (よくわかりません)。
  2. このクラスは巨大な IBM クライアント ライブラリ com.ibm.ws.admin.client-7.0.0.jar (42 Mo) で定義されています => コンパイルが遅く、私のエンタープライズ ネクサスには存在しません
  3. ポータブルではなく、標準ではありません

WebsphereCredentials参考までに、コンストラクターを次のように定義します。

Map<String, String> map = new HashMap<String, String>();

map.put(Constants.MAPPING_ALIAS, this.jndiAlias);
Subject subject;
try {
    CallbackHandler callbackHandler = WSMappingCallbackHandlerFactory.getInstance().getCallbackHandler(map, null);
    LoginContext lc = new LoginContext("DefaultPrincipalMapping", callbackHandler);
    lc.login();
    subject = lc.getSubject();
} catch (NotImplementedException e) {
    throw new EfritTechnicalException(EfritTechnicalExceptionEnum.LOGIN_CREDENTIAL_PROBLEM, e);
} catch (LoginException e) {
    throw new EfritTechnicalException(EfritTechnicalExceptionEnum.LOGIN_CREDENTIAL_PROBLEM, e);
}

PasswordCredential cred = (PasswordCredential) subject.getPrivateCredentials().toArray()[0];

this.user = cred.getUserName();
this.password = String.valueOf(cred.getPassword());

Spring セキュリティだけを使用して、この依存関係を削除する方法はありますか?

http://static.springsource.org/spring-security/site/docs/3.1.x/reference/jaas.htmlhttp://static.springsource.org/spring-security/siteを組み合わせる方法がわかりません/docs/3.1.x/reference/ldap.html .

多分私は自分のアプローチを完全に変えて別の方法を使わなければならないのでしょうか?

4

1 に答える 1

5

あなたの目標は、WebSphereで設定したユーザー名/パスワードを単純に利用してLDAPディレクトリに接続することだと思いますか? この場合、実際には LDAP と JAAS ベースの認証を組み合わせようとしているわけではありません。JAAS サポートはLoginModule、LDAP ベースの認証を使用する代わりに、JAAS を使用してユーザーを認証する方法を意図しています。

コンパイル時に WebSphere に依存せずにユーザー名とパスワードを取得したい場合は、いくつかのオプションがあります。

WAS でのコンパイル時間とランタイムの依存関係を排除する

1 つのオプションは、別の方法でパスワードを構成することです。これは、 Spring Security LDAP ドキュメントに示されているように、構成ファイルで直接パスワードを直接使用するのと同じくらい簡単です。

<bean id="ldapContextSource"
        class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
  <constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/>
  <property name="userDn" value="cn=manager,dc=springframework,dc=org"/>
  <property name="password" value="password"/>
</bean>

JNDI でユーザー名パスワードを構成することもできます。もう 1 つの方法は、Property で .properties ファイルを使用することです。パスワードを確実に保護したい場合は、Jasyptなどを使用してパスワードを暗号化することをお勧めします。

コンパイル時の依存関係を排除し、WAS を使用して構成する

クレデンシャルを格納するために WebSphere の J2C サポートが必要な場合、または使用したい場合は、CallbackHandlerインスタンスを注入することで実行できます。たとえば、WebsphereCredentialsBean は次のようになります。

try {
    LoginContext lc = new LoginContext("DefaultPrincipalMapping", this.callbackHandler);
    lc.login();
    subject = lc.getSubject();
} catch (NotImplementedException e) {
    throw new EfritTechnicalException(EfritTechnicalExceptionEnum.LOGIN_CREDENTIAL_PROBLEM, e);
} catch (LoginException e) {
    throw new EfritTechnicalException(EfritTechnicalExceptionEnum.LOGIN_CREDENTIAL_PROBLEM, e);
}

PasswordCredential cred = (PasswordCredential) subject.getPrivateCredentials().toArray()[0];

this.user = cred.getUserName();
this.password = String.valueOf(cred.getPassword());

構成は次のようになります。

<bean id="userConnexion" class="com.myapp.util.security.WebsphereCredentials">
    <constructor-arg ref="wasCallbackHandler"/>
</bean>

<bean id="wasCallbackHandler"
      factory-bean="wasCallbackFactory"
      factory-method="getCallbackHandler">
    <constructor-arg>
      <map>
        <entry
            value="${ldap.authJndiAlias}">
          <key>
            <util:constant static-field="com.ibm.wsspi.security.auth.callback.Constants.MAPPING_ALIAS"/>
          </key>
        </entry>
      </map>
    </constructor-arg>
    <constructor-arg>
      <null />
    </constructor-arg>
</bean>

<bean id="wasCallbackFactory"
    class="com.ibm.wsspi.security.auth.callback.WSMappingCallbackHandlerFactory"
    factory-method="getInstance" />

免責事項

CallbackHandlerインスタンスはスレッド セーフではないため、通常は複数回使用しないでください。CallbackHandlerしたがって、インスタンスをメンバー変数として注入するのは少し危険です。CallbackHandler一度だけ使用されることを確認するために、チェックをプログラムすることができます。

ハイブリッドアプローチ

コンパイル時の依存関係を常に削除し、WebSphere で実行していない可能性のあるインスタンスでランタイムの依存関係を削除できるハイブリッド アプローチを実行できます。これは、2 つの提案を組み合わせ、Spring Bean 定義プロファイルを使用して、WebSphere での実行と WebSphere 以外のマシンでの実行を区別することで実現できます。

于 2012-12-27T20:24:15.680 に答える