Class LdapLoginModule

java.lang.Object
com.sun.security.auth.module.LdapLoginModule
所有已实现的接口:
LoginModule

public class LdapLoginModule extends Object implements LoginModule
这个LoginModule执行基于LDAP的身份验证。用户名和密码将与存储在LDAP目录中的相应用户凭据进行验证。此模块需要提供的CallbackHandler支持一个NameCallback和一个PasswordCallback。如果身份验证成功,则使用用户的专有名称创建一个新的LdapPrincipal,并使用用户的用户名创建一个新的UserPrincipal,并将它们与当前的Subject关联。

此模块以三种模式之一运行:search-firstauthentication-firstauthentication-only。通过指定特定的选项来选择模式。

在search-first模式下,将搜索LDAP目录以确定用户的专有名称,然后尝试进行身份验证。使用提供的用户名与指定的搜索过滤器执行(匿名)搜索。如果成功,则尝试使用用户的专有名称和提供的密码进行身份验证。要启用此模式,请设置userFilter选项并省略authIdentity选项。当用户的专有名称事先不知道时,请使用search-first模式。

在authentication-first模式下,使用提供的用户名和密码尝试进行身份验证,然后搜索LDAP目录。如果身份验证成功,则使用提供的用户名与指定的搜索过滤器执行搜索。要启用此模式,请设置authIdentityuserFilter选项。当访问已配置为禁止匿名搜索的LDAP目录时,请使用authentication-first模式。

在authentication-only模式下,使用提供的用户名和密码尝试进行身份验证。不搜索LDAP目录,因为用户的专有名称已知。要启用此模式,请将authIdentity选项设置为有效的专有名称,并省略userFilter选项。当用户的专有名称事先已知时,请使用authentication-only模式。

以下选项是强制性的,并且必须在此模块的登录Configuration中指定:

userProvider=ldap_urls
此选项标识存储用户条目的LDAP目录。ldap_urls是一个以空格分隔的LDAP URL列表(RFC 2255),用于标识要使用的LDAP服务器以及其目录树中用户条目的位置。如果指定了多个LDAP URL,则会依次尝试每个,直到建立第一个成功的连接。URL的专有名称组件中的空格必须使用百分比字符('%')后跟两个十六进制数字的标准机制进行转义(请参阅URI)。还必须从URL中省略查询组件。

通过DNS(RFC 2782)自动发现LDAP服务器受支持(一旦配置DNS以支持此类服务)。通过省略LDAP URL中的主机名和端口号组件来启用此功能。

此模块还识别以下可选的Configuration选项:

userFilter=ldap_filter
此选项指定用于在LDAP目录中定位用户条目的搜索过滤器。用于确定用户的专有名称。 ldap_filter是一个LDAP过滤器字符串(RFC 2254)。如果它包含特殊标记"{USERNAME}",则该标记将在使用过滤器搜索目录之前替换为提供的用户名值。
authIdentity=auth_id
此选项指定在向LDAP目录验证用户时要使用的身份。 auth_id可以是LDAP专有名称字符串(RFC 2253)或其他字符串名称。它必须包含特殊标记"{USERNAME}",该标记将在用于身份验证之前用提供的用户名值替换。请注意,如果此选项不包含专有名称,则还必须指定userFilter选项。
authzIdentity=authz_id
此选项为用户指定授权身份。 authz_id是任何字符串名称。如果它包含带大括号的单个特殊标记,则该标记将被视为属性名称,并将从用户的LDAP条目中的该属性的单个值替换为该值。如果找不到属性,则将忽略该选项。当提供此选项并且用户已成功验证时,将使用授权身份创建一个额外的UserPrincipal,并将其与当前的Subject关联。
useSSL
如果为false,则此模块在尝试身份验证之前不会与LDAP服务器建立SSL连接。使用SSL用于保护用户密码的隐私,因为它在LDAP上以明文传输。默认情况下,此模块使用SSL。
useFirstPass
如果为true,则此模块从模块的共享状态中检索用户名和密码,使用"javax.security.auth.login.name"和"javax.security.auth.login.password"作为相应的键。检索的值用于身份验证。如果身份验证失败,则不会尝试重试,并将失败报告给调用应用程序。
tryFirstPass
如果为true,则此模块从模块的共享状态中检索用户名和密码,使用"javax.security.auth.login.name"和"javax.security.auth.login.password"作为相应的键。检索的值用于身份验证。如果身份验证失败,则模块使用CallbackHandler检索新的用户名和密码,并尝试进行另一次身份验证。如果身份验证失败,则将失败报告给调用应用程序。
storePass
如果为true,则此模块将从CallbackHandler获取的用户名和密码存储在模块的共享状态中,使用"javax.security.auth.login.name"和"javax.security.auth.login.password"作为相应的键。如果共享状态中已存在用户名和密码的现有值,或者身份验证失败,则不执行此操作。
clearPass
如果为true,则此模块在身份验证的两个阶段(登录和提交)完成后清除存储在模块的共享状态中的用户名和密码。
debug
如果为true,则在标准输出流上显示调试消息。

还可以在"JNDI属性"中指定任意的Configuration。它们将添加到环境并传递给LDAP提供程序。请注意,此模块直接设置以下四个JNDI属性,并且如果这些属性也存在于配置中,则会被忽略:

  • java.naming.provider.url
  • java.naming.security.principal
  • java.naming.security.credentials
  • java.naming.security.protocol

下面显示了三个示例Configuration。第一个激活search-first模式。它标识LDAP服务器,并指定用户条目通过其uidobjectClass属性进行定位。还指定应创建基于用户employeeNumber属性的身份。第二个激活authentication-first模式。它请求动态定位LDAP服务器,使用提供的用户名直接执行身份验证,但不使用SSL保护,并且用户条目通过三个命名属性之一和它们的objectClass属性进行定位。第三个激活authentication-only模式。它标识备用LDAP服务器,指定用于身份验证的专有名称和用于授权的固定身份。不执行目录搜索。

     ExampleApplication {
         com.sun.security.auth.module.LdapLoginModule REQUIRED
              userProvider="ldap://ldap-svr/ou=people,dc=example,dc=com"
              userFilter="(&(uid={USERNAME})(objectClass=inetOrgPerson))"
              authzIdentity="{EMPLOYEENUMBER}"
              debug=true;
     };

     ExampleApplication {
         com.sun.security.auth.module.LdapLoginModule REQUIRED
             userProvider="ldap:///cn=users,dc=example,dc=com"
             authIdentity="{USERNAME}"
             userFilter="(&(|(samAccountName={USERNAME})(userPrincipalName={USERNAME})(cn={USERNAME}))(objectClass=user))"
             useSSL=false
             debug=true;
     };

     ExampleApplication {
         com.sun.security.auth.module.LdapLoginModule REQUIRED
             userProvider="ldap://ldap-svr1 ldap://ldap-svr2"
             authIdentity="cn={USERNAME},ou=people,dc=example,dc=com"
             authzIdentity="staff"
             debug=true;
     };

 
注意:
当一个活动的SecurityManager时,创建一个LoginContext并使用LoginModule的应用程序必须被授予某些权限。

如果应用程序使用一个已安装的Configuration创建登录上下文,则该应用程序必须被授予创建登录上下文的AuthPermission。例如,以下安全策略允许用户当前目录中的应用程序实例化任何登录上下文:

     grant codebase "file:${user.dir}/" {
         permission javax.security.auth.AuthPermission "createLoginContext.*";
     };
     
或者,如果应用程序使用调用者指定的Configuration创建登录上下文,则该应用程序必须被授予LoginModule所需的权限。 模块需要以下两个权限:

例如,以下安全策略授予用户当前目录中的应用程序此模块所需的所有权限:

     grant codebase "file:${user.dir}/" {
         permission java.net.SocketPermission "*:389", "connect";
         permission java.net.SocketPermission "*:636", "connect";
         permission javax.security.auth.AuthPermission "modifyPrincipals";
     };
     
自1.6版本起:
1.6
  • Constructor Details

    • LdapLoginModule

      public LdapLoginModule()
      创建一个LdapLoginModule
  • Method Details

    • initialize

      public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String,?> sharedState, Map<String,?> options)
      初始化这个LoginModule
      指定者:
      initialize 在接口 LoginModule
      参数:
      subject - 要进行身份验证的Subject
      callbackHandler - 一个CallbackHandler用于获取用户名和密码。
      sharedState - 共享的LoginModule状态。
      options - 在此特定LoginModule的登录Configuration中指定的选项。
    • login

      public boolean login() throws LoginException
      开始用户认证。

      获取用户的凭据并根据指定的LDAP目录进行验证。

      指定者:
      login 在接口 LoginModule
      返回:
      始终为true,因为这个LoginModule不应被忽略。
      抛出:
      FailedLoginException - 如果认证失败。
      LoginException - 如果这个LoginModule无法执行认证。
    • commit

      public boolean commit() throws LoginException
      完成用户认证。

      如果LoginContext的整体认证成功(相关的REQUIRED、REQUISITE、SUFFICIENT和OPTIONAL LoginModules成功),则调用此方法。

      如果这个LoginModule自己的认证尝试成功(通过检索login方法保存的私有状态来检查),则此方法将在LoginModule中的Subject上关联一个LdapPrincipal和一个或多个UserPrincipal。如果这个LoginModule自己的认证尝试失败,则此方法将删除最初保存的任何状态。

      指定者:
      commit 在接口 LoginModule
      返回:
      如果这个LoginModule自己的登录和提交尝试成功,则为true,否则为false。
      抛出:
      LoginException - 如果提交失败
    • abort

      public boolean abort() throws LoginException
      中止用户认证。

      如果整体认证失败,则调用此方法。(相关的REQUIRED、REQUISITE、SUFFICIENT和OPTIONAL LoginModules未成功)。

      如果这个LoginModule自己的认证尝试成功(通过检索logincommit方法保存的私有状态来检查),则此方法将清除最初保存的任何状态。

      指定者:
      abort 在接口 LoginModule
      返回:
      如果这个LoginModule自己的登录和/或提交尝试失败,则为false,否则为true。
      抛出:
      LoginException - 如果中止失败。
    • logout

      public boolean logout() throws LoginException
      注销用户。

      此方法将删除由commit方法添加的Principal。

      指定者:
      logout 在接口 LoginModule
      返回:
      在所有情况下都为true,因为这个LoginModule不应被忽略。
      抛出:
      LoginException - 如果注销失败。