1011.md 6.4 KB
Newer Older
W
init  
wizardforcel 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
# 对 LDAP 进行身份验证的模式

> 原文: [https://docs.oracle.com/javase/tutorial/jndi/ldap/authentication.html](https://docs.oracle.com/javase/tutorial/jndi/ldap/authentication.html)

在 LDAP 中,身份验证信息在“绑定”操作中提供。在 LDAP v2 中,客户端通过向服务器发送包含身份验证信息的“绑定”操作来启动与 LDAP 服务器的连接。

在 LDAP v3 中,此操作用于相同的目的,但它是可选的。发送 LDAP 请求而不执行“绑定”的客户端被视为 _ 匿名 _ 客户端(有关详细信息,请参阅[匿名](anonymous.html)部分)。在 LDAP v3 中,“绑定”操作可以在连接期间的任何时间发送,可能不止一次。客户端可以在连接中间发送“绑定”请求以更改其标识。如果请求成功,则丢弃在连接上使用旧标识的所有未完成请求,并且连接与新标识关联。

“绑定”操作中提供的认证信息取决于客户端选择的 _ 认证机制 _。有关身份验证机制的讨论,请参阅[身份验证机制](auth_mechs.html)

## 使用 JNDI 对 LDAP 进行身份验证

在 JNDI 中,身份验证信息在环境属性中指定。当您使用 [`InitialDirContext`](https://docs.oracle.com/javase/8/docs/api/javax/naming/directory/InitialDirContext.html)类(或其超类或子类)创建初始上下文时,您提供了一组环境属性,其中一些可能包含身份验证信息。您可以使用以下环境属性来指定身份验证信息。

*   [`Context.SECURITY_AUTHENTICATION` ](https://docs.oracle.com/javase/8/docs/api/javax/naming/Context.html#SECURITY_AUTHENTICATION)`“java.naming.security.authentication”`)。
    指定要使用的身份验证机制。对于 JDK 中的 LDAP 服务提供者,这可以是以下字符串之一:`“无”``“简单”`, _sasl_mech_ ,其中 _sasl_mech_ 是一个以空格分隔的 SASL 机制名称列表。有关这些字符串的说明,请参见[验证机制](auth_mechs.html)
*   [`Context.SECURITY_PRINCIPAL` ](https://docs.oracle.com/javase/8/docs/api/javax/naming/Context.html#SECURITY_PRINCIPAL)`“java.naming.security.principal”`)。
    指定进行身份验证的用户/程序的名称,并取决于 `Context.SECURITY_AUTHENTICATION` 属性的值。有关详细信息和示例,请参阅本课程的下几节。
*   [`Context.SECURITY_CREDENTIALS` ](https://docs.oracle.com/javase/8/docs/api/javax/naming/Context.html#SECURITY_CREDENTIALS)`“java.naming.security.credentials”`)。
    指定进行身份验证的用户/程序的凭据,并取决于 `Context.SECURITY_AUTHENTICATION` 属性的值。有关详细信息和示例,请参阅本课程的下几节。

W
wizardforcel 已提交
22
创建初始上下文时,基础 LDAP 服务供应器从这些环境属性中提取身份验证信息,并使用 LDAP“绑定”操作将它们传递给服务器。
W
init  
wizardforcel 已提交
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112

[`following example`](examples/Simple.java) 通过使用简单的明文密码显示客户端如何向 LDAP 服务器进行身份验证。

```
// Set up the environment for creating the initial context
Hashtable<String, Object> env = new Hashtable<String, Object>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

// Authenticate as S. User and password "mysecret"
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, 
        "cn=S. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "mysecret");

// Create the initial context
DirContext ctx = new InitialDirContext(env);

// ... do something useful with ctx

```

## 为上下文使用不同的身份验证信息

如果要对现有上下文使用不同的身份验证信息,则可以使用 [`Context.addToEnvironment()`](https://docs.oracle.com/javase/8/docs/api/javax/naming/Context.html#addToEnvironment-java.lang.String-java.lang.Object-)[`Context.removeFromEnvironment()`](https://docs.oracle.com/javase/8/docs/api/javax/naming/Context.html#removeFromEnvironment-java.lang.String-) 更新包含身份验证信息的环境属性。对上下文的方法的后续调用将使用新的认证信息与服务器通信。

[`following example`](examples/UseDiff.java) 显示在创建上下文后如何将上下文的认证信息更改为`“无”`

```
// Authenticate as S. User and the password "mysecret"
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, 
        "cn=S. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "mysecret");

// Create the initial context
DirContext ctx = new InitialDirContext(env);

// ... do something useful with ctx

// Change to using no authentication
ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "none");

// ... do something useful with ctx

```

## 身份验证失败

身份验证可能由于多种原因而失败。例如,如果您提供不正确的身份验证信息,例如密码或主体名称不正确,则会抛出 [`AuthenticationException`](https://docs.oracle.com/javase/8/docs/api/javax/naming/AuthenticationException.html)

这是 [`an example`](examples/BadPasswd.java) ,它是前一个例子的变体。这次,密码错误会导致身份验证失败。

```
// Authenticate as S. User and give an incorrect password
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, 
        "cn=S. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "notmysecret");

```

这会产生以下输出。

```
javax.naming.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]
        ...

```

由于不同的服务器支持不同的身份验证机制,因此您可能会请求服务器不支持的身份验证机制。在这种情况下,将抛出 [`AuthenticationNotSupportedException`](https://docs.oracle.com/javase/8/docs/api/javax/naming/AuthenticationNotSupportedException.html)

这是 [`an example`](examples/BadAuth.java) ,它是前一个例子的变体。这次,不支持的身份验证机制(`“custom”`)导致身份验证失败。

```
// Authenticate as S. User and the password "mysecret"
env.put(Context.SECURITY_AUTHENTICATION, "custom");
env.put(Context.SECURITY_PRINCIPAL, 
        "cn=S. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "mysecret");

```

这会产生以下输出。

```
javax.naming.AuthenticationNotSupportedException: custom
        ...

```