Java 使用SpringLDAP对Active Directory进行身份验证的FastBind
我有一个SpringMVC应用程序(使用3.0.5版本),需要使用SpringLDAP绑定到Active Directory,以便简单且仅验证用户的凭据。该应用程序托管在Linux服务器上,因此我需要一个跨平台的解决方案。并且应用程序不使用Spring安全性 在此设置中实现用户身份验证的有效方法是什么?Active Directory支持Java 使用SpringLDAP对Active Directory进行身份验证的FastBind,java,spring,authentication,active-directory,ldap,Java,Spring,Authentication,Active Directory,Ldap,我有一个SpringMVC应用程序(使用3.0.5版本),需要使用SpringLDAP绑定到Active Directory,以便简单且仅验证用户的凭据。该应用程序托管在Linux服务器上,因此我需要一个跨平台的解决方案。并且应用程序不使用Spring安全性 在此设置中实现用户身份验证的有效方法是什么?Active Directory支持FastBind控件(id=1.2.840.113556.1.4.1781),因此我想利用它,因为我只需要验证输入凭据,不需要从AD返回其他信息 谢谢 更新(7
FastBind
控件(id=1.2.840.113556.1.4.1781
),因此我想利用它,因为我只需要验证输入凭据,不需要从AD返回其他信息
谢谢
更新(7/16/2012):我将继续更新我的问题和决议的细节
根据@ig0774的回答,我编写了以下连接控制类:
package com.company.authentication;
import javax.naming.ldap.Control;
public class FastBindConnectionControl implements Control {
@Override
public String getID() {
return "1.2.840.113556.1.4.1781";
}
@Override
public boolean isCritical() {
return true;
}
@Override
public byte[] getEncodedValue() {
return null;
}
}
然后,我使用FastBind
连接控制类扩展了AbstractContextSource
:
package com.company.authentication;
import java.util.Hashtable;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import org.springframework.ldap.core.support.AbstractContextSource;
public class FastBindActiveDirectoryContextSource extends AbstractContextSource {
@Override
protected DirContext getDirContextInstance(Hashtable env) throws NamingException {
return new InitialLdapContext(env, new Control[] { new FastBindConnectionControl() });
}
}
最后,一个封装身份验证机制的服务类:
package com.company.authentication;
import javax.naming.AuthenticationException;
import javax.naming.directory.DirContext;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.support.LdapUtils;
public class ActiveDirectoryAuthService implements IAuthenticate {
private ContextSource contextSource;
public void setContextSource(ContextSource contextSource) {
this.contextSource = contextSource;
}
@Override
public boolean authenticate(final String login, String password) {
try {
DirContext ctx = contextSource.getContext(login, password);
LdapUtils.closeContext(ctx);
return true;
}
catch (Exception e) {
return false;
}
}
}
在我的Spring应用程序上下文配置文件中,我添加了以下内容:
<bean id="ADContextSource" class="com.company.authentication.FastBindActiveDirectoryContextSource">
<property name="url" value="ldaps://x.x.x.x:636" />
</bean>
<bean id="userAuthenticationService" class="com.company.authentication.ActiveDirectoryAuthService">
<property name="contextSource" ref="ADContextSource" />
</bean>
由于FastBind
仅“检查用户的凭据”,不执行组确定,因此最好使用可分辨名称和凭据将绑定请求发送到服务器。任何简单的绑定请求都应该通过安全连接传输。结果代码为0
(零)的响应表示:
服务器正在侦听和响应
可分辨名称存在,并且凭据与存储在服务器数据库中的凭据匹配
LDAP客户端具有足够的访问权限来验证服务器上的会话
是与目录服务器交互的最佳Java实现由于快速绑定
仅“检查用户的凭据”,不执行组确定,因此最好只使用可分辨名称和凭据向服务器发送绑定请求。任何简单的绑定请求都应该通过安全连接传输。结果代码为0
(零)的响应表示:
服务器正在侦听和响应
可分辨名称存在,并且凭据与存储在服务器数据库中的凭据匹配
LDAP客户端具有足够的访问权限来验证服务器上的会话
是与目录服务器交互的最佳Java实现在JNDI中实现FastBind
控件是非常直接的
基本上,您可以为FastBind
控件创建一个新的Control
类:
class FastBindConnectionControl implements Control {
public byte[] getEncodedValue() {
return null;
}
public String getID() {
return "1.2.840.113556.1.4.1781";
}
public boolean isCritical() {
return true;
}
}
然后使用它来创建ldap上下文(错误处理和忽略所有其他内容):
理想情况下,这将很容易插入SpringLDAP,SpringLDAP是用于LDAP的JNDIAPI的包装器;但是,内置接口似乎不接受处理连接控件的参数,因此您显然需要创建自己的子类来处理该问题,这看起来应该足够简单:
class FastBindLdapContextSource extends AbstractContextSource {
protected DirContext getDirContextInstance(Hashtable env) {
return new InitialLdapContext(env, new Control[] {new FastBindConnectionControl()});
}
}
然后,您只需要将当前的LdapContextSource
替换为FastBindLdapContextSource
的实例
但是,请注意,此上下文源只能用于BIND
操作。正如我在给特里·加德纳的评论中提到的:
在此模式下,连接上只接受简单绑定。因为没有进行组计算,所以连接的处理总是如同所有其他LDAP操作都没有发生绑定一样
这意味着您可能需要维护两种类型的LDAP上下文,一种用于绑定,另一种用于实际执行您可能需要执行的任何查找
查看,我看到authenticate
方法看起来不仅仅是一个简单的绑定。更具体地说,它搜索用户,然后尝试绑定。因为,如果使用启用了FastBind
的上下文,则不太可能执行搜索(通常AD不允许对匿名连接进行搜索)。基本上,这意味着您可能必须避免使用LdapTemplate
然而,假设您获得了对AdContextSourcebean的引用,它应该足够简单,可以执行以下操作
boolean authenticate(String username, String password) {
try {
DirContext ctx = contextSource.getContext(username, password);
LdapUtils.closeContext(ctx);
return true;
} catch (Exception e) {
// note: this means an exception was thrown by #getContext() above
return false;
}
}
它非常接近于LdapTemplate
将要做的事情(唯一缺少的是AuthenticatedLdapEntryContextCallback
,它在本场景中没有任何价值,以及AuthenticationErrorCallback
,如果您想要这种行为,可以很容易地添加到其中)如前所述,在JNDI中实现FastBind
控件非常简单
基本上,您可以为FastBind
控件创建一个新的Control
类:
class FastBindConnectionControl implements Control {
public byte[] getEncodedValue() {
return null;
}
public String getID() {
return "1.2.840.113556.1.4.1781";
}
public boolean isCritical() {
return true;
}
}
然后使用它来创建ldap上下文(错误处理和忽略所有其他内容):
理想情况下,这将很容易插入SpringLDAP,SpringLDAP是用于LDAP的JNDIAPI的包装器;但是,内置接口似乎不接受处理连接控件的参数,因此您显然需要创建自己的子类来处理该问题,这看起来应该足够简单:
class FastBindLdapContextSource extends AbstractContextSource {
protected DirContext getDirContextInstance(Hashtable env) {
return new InitialLdapContext(env, new Control[] {new FastBindConnectionControl()});
}
}
然后,您只需要将当前的LdapContextSource
替换为FastBindLdapContextSource
的实例
但是,请注意,此上下文源只能用于BIND
操作。正如我在给特里·加德纳的评论中提到的:
在此模式下,连接上只接受简单绑定。因为没有进行组计算,所以连接总是像没有绑定一样处理