authentication - 将 JAAS 用于具有 Spring 安全性的 LDAP 密码

标签 authentication spring-security ldap websphere jaas

我有一个使用 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 WebsphereCredentials使用 WebSphere 私有(private)类 WSMappingCallbackHandlerFactory如本回复:How to access authentication alias from EJB deployed to Websphere 6.1

我们可以在 websphere 官方文档中看到:http://pic.dhe.ibm.com/infocenter/wasinfo/v6r1/index.jsp?topic=%2Fcom.ibm.websphere.express.doc%2Finfo%2Fexp%2Fae%2Frsec_pluginj2c.html

但我不想要它,因为:
  • 我认为我的应用程序可以访问我的 WebSphere 实例中的所有 JAAS 登录(不确定)。
  • 此类定义在巨大的 IBM 客户端库 com.ibm.ws.admin.client-7.0.0.jar (42 Mo) => 编译速度较慢,在我的企业关系中不存在
  • 它不便携,不标准

  • 有关信息,我定义了 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 .

    也许我必须完全改变我的方法并使用另一种方式?

    最佳答案

    我假设您的目标是简单地使用您在 WebSphere 中配置的用户名/密码来连接到 LDAP 目录?如果是这种情况,您并没有真正尝试结合 LDAP 和基于 JAAS 的身份验证。 JAAS 支持实际上是一种使用 JAAS 的方式 LoginModule s 对用户进行身份验证,而不是使用基于 LDAP 的身份验证。

    如果您想获得用户名和密码而不依赖于 WebSphere 的编译时,您有几个选择。

    消除对 WAS 的编译时间和运行时依赖性

    一种选择是以不同的方式配置密码。这可以像直接在配置文件中直接使用密码一样简单,如 Spring Security LDAP documentation 所示。 :

    <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 中配置用户名密码。另一种选择是使用带有属性的 .properties 文件。如果您想确保密码是安全的,那么您可能需要使用类似 Jasypt 的方式来加密密码。 .

    消除编译时依赖并仍然使用 WAS 进行配置

    如果您需要或想要使用 WebSphere 的 J2C 支持来存储凭证,那么您可以通过注入(inject) CallbackHandler 来实现。实例。例如,您的 WebsphereCredentials bean 可能是这样的:
    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实例不是线程安全的,通常不应多次使用。因此注入(inject) CallbackHandler 可能有点冒险。实例作为成员变量。您可能需要编写检查程序以确保 CallbackHandler只用过一次。

    混合方法

    您可以采用一种混合方法,该方法始终删除编译时依赖项,并允许您在可能未在 WebSphere 上运行的实例中删除运行时依赖项。这可以通过结合这两个建议并使用 Spring Bean Definition Profiles 来完成。以区分在 WebSphere 和非 WebSphere 机器上运行。

    关于authentication - 将 JAAS 用于具有 Spring 安全性的 LDAP 密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14039038/

    相关文章:

    java - 通过Java更新LDAP时如何指定哈希算法?

    java - Spring 安全 : Redirecting to login page if the authentication failed

    php - 用户登录和 session :Safe or Not

    session - 可扩展 Web 应用程序的无状态登录/身份验证机制?

    authentication - LDAP 服务器,这是我的基础 dn

    java - 我如何将 Spring Security 与具有 session 复制功能的集群一起使用以对经过身份验证的用户进行故障转移?

    java - 无法自动接线。找不到 'AuthenticationProvider' 类型的 bean

    spring-security - OWASP 十大攻击与 Spring Security

    spring-security - gradle测试挂起,用于带有嵌入式ldap服务器的 Spring 安全性测试

    spring-security - Spring LDAP PasswordEncoder 已弃用的替代方案