博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
通过LDAP验证Active Directory服务
阅读量:2506 次
发布时间:2019-05-11

本文共 7317 字,大约阅读时间需要 24 分钟。

这一周做LDAP做得头都大了。现在终于有点头绪了,记录一下,以备后用。

 

LDAP是什么?

LDAP是轻量级目录访问协议,英文全称是Lightweight Directory Access Protocol,一般都简称为LDAP.
一般用来构建集中的身份验证系统可以减少管理成本,增强安全性,避免数据复制的问题,并提高数据的一致性。

ActiveDirectory是什么?

Active Directory存储了有关网络对象的信息,并且让管理员和用户能够轻松地查找和使用这些信息。Active Directory使用了一种结构化的数据存储方式,并以此作为基础对目录信息进行合乎逻辑的分层组织。
①基础网络服务:包括DNS、WINS、DHCP、证书服务等。

 

②服务器及客户端计算机管理:管理服务器及客户端计算机账户,所有服务器及客户端计算机加入域管理并实施组策略。

 

③用户服务:管理用户域账户、用户信息、企业通讯录(与电子邮件系统集成)、用户组管理、用户身份认证、用户授权管理等,按省实施组管理策略。

 

④资源管理:管理打印机、文件共享服务等网络资源。

 

⑤桌面配置:系统管理员可以集中的配置各种桌面配置策略,如:界面功能的限制、应用程序执行特征限制、网络连接限制、安全配置限制等。

 

s⑥应用系统支撑:支持财务、人事、电子邮件、企业信息门户、办公自动化、补丁管理、防病毒系统等各种应用系统。

-------------------------------------------------------------------------------

概念都是搜出来的,不是一般的抽象。这也是我花了近一周时间才弄懂一点的原因所在。

我的理解是可以把mirectory的ActiveDirectory当作一个LDAP服务器,提供LDAP验证服务。当然其他平台或公司也有自己的ldap服务器。如sun,ibm,等的。

我的需求是在EOS开发平台(基于EclipseJAVA工作流)上通过内嵌的开源ABFrame(权限管理系统)实现LDAP验证,

进而实现SSO。
找到了LDAP的配置文件后经过查找资料无论如何也通不过验证,还跟了很深的代码,JNDI的资料也查了很多,无果。

 

无奈,微软自己家东西,就试着用.net写了个程序,没有什么障碍,很简单就通过了登陆验证。代码如下:

ldap C#
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.DirectoryServices;
using
System.Configuration;
using
System.Text.RegularExpressions;
namespace
ldapcs
{
class
Program
{
static
void
Main(
string
[] args)
{
string
path
=
"
LDAP://192.168.137.210:389/ou=pet,dc=abc,dc=com
"
;
string
username
=
"
uname
"
;
string
pwd
=
"
upwd
"
;
string
domain
=
"
abc.com
"
;
LdapAuthentication ldap
=
new
LdapAuthentication(path);
Console.WriteLine( ldap.IsAuthenticated(domain, username, pwd));
Console.WriteLine(ldap.GetGroups());
}
public
class
LdapAuthentication
{
private
string
_path;
private
string
_filterAttribute;
public
LdapAuthentication(
string
path)
{
_path
=
path;
}
public
bool
IsAuthenticated(
string
domain,
string
username,
string
pwd)
{
string
domainAndUsername
=
domain
+
@"
\
"
+
username;
DirectoryEntry entry
=
new
DirectoryEntry(_path, username, pwd);
try
{
//
Bind to the native AdsObject to force authentication.
object
obj
=
entry.NativeObject;
DirectorySearcher search
=
new
DirectorySearcher(entry);
search.Filter
=
"
(SAMAccountName=
"
+
username
+
"
)
"
;
search.PropertiesToLoad.Add(
"
cn
"
);
SearchResult result
=
search.FindOne();
if
(
null
==
result)
{
return
false
;
}
//
Update the new path to the user in the directory.
_path
=
result.Path;
_filterAttribute
=
(
string
)result.Properties[
"
cn
"
][
0
];
}
catch
(Exception ex)
{
throw
new
Exception(
"
Error authenticating user.
"
+
ex.Message);
}
return
true
;
}
public
string
GetGroups()
{
DirectorySearcher search
=
new
DirectorySearcher(_path);
search.Filter
=
"
(cn=
"
+
_filterAttribute
+
"
)
"
;
//
search.SearchRoot = "PET";
StringBuilder groupNames
=
new
StringBuilder();
try
{
SearchResult result
=
search.FindOne();
int
propertyCount
=
result.Properties[
"
memberOf
"
].Count;
string
dn;
int
equalsIndex, commaIndex;
for
(
int
propertyCounter
=
0
; propertyCounter
<
propertyCount; propertyCounter
++
)
{
dn
=
(
string
)result.Properties[
"
memberOf
"
][propertyCounter];
equalsIndex
=
dn.IndexOf(
"
=
"
,
1
);
commaIndex
=
dn.IndexOf(
"
,
"
,
1
);
if
(
-
1
==
equalsIndex)
{
return
null
;
}
groupNames.Append(dn.Substring((equalsIndex
+
1
), (commaIndex
-
equalsIndex)
-
1
));
groupNames.Append(
"
|
"
);
}
}
catch
(Exception ex)
{
throw
new
Exception(
"
Error obtaining group names.
"
+
ex.Message);
}
return
groupNames.ToString();
}
}
///
<summary>
///
验证AD用户是否登录成功
///
</summary>
///
<param name="domain"></param>
///
<param name="userName"></param>
///
<param name="password"></param>
///
<returns></returns>
public
static
bool
TryAuthenticate(
string
domain,
string
userName,
string
password)
{
bool
isLogin
=
false
;
try
{
DirectoryEntry entry
=
new
DirectoryEntry(
string
.Format(
"
LDAP://{0}
"
, domain), userName, password);
entry.RefreshCache();
isLogin
=
true
;
}
catch
{
isLogin
=
false
;
}
return
isLogin;
}
}
}

 

再回头去用abframe的东西,还是没有结果。于是再找一个java验证的例子,还是可以通过验证

代码
/**
*
*
@author
icuit
*/
import
java.util.Hashtable;
import
java.util.Enumeration;
import
javax.naming.Context;
import
javax.naming.NamingException;
import
javax.naming.directory.DirContext;
import
javax.naming.directory.InitialDirContext;
import
javax.naming.directory.SearchControls ;
import
javax.naming.NamingEnumeration;
import
javax.naming.directory.SearchResult;
public
class
LDAPtest {
public
static
void
main(String[] args) {
LDAPtest ldap
=
new
LDAPtest();
ldap.init();
}
public
void
init(){
DirContext ctx
=
null
;
Hashtable env
=
new
Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"
com.sun.jndi.ldap.LdapCtxFactory
"
);
env.put(Context.PROVIDER_URL,
"
ldap://192.168.137.210:389/
"
);
//
连接LDAP的URL和端口
//
env.put(Context.SECURITY_AUTHENTICATION, "simple");
//
以simple方式发送
env.put(Context.SECURITY_PRINCIPAL,
"
cn=uname,ou=PET,DC=abc,DC=com
"
);
//
用户名
env.put(Context.SECURITY_CREDENTIALS,
"
upwd
"
);
//
密码
String baseDN
=
"
ou=PET,DC=abc,DC=com
"
;
//
查询区域
String filter
=
"
(&(objectClass=person))
"
;
//
条件查询
try
{
ctx
=
new
InitialDirContext(env);
//
连接LDAP服务器
System.out.println(
"
Success
"
);
SearchControls constraints
=
new
SearchControls();
//
执行查询操作
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration en
=
ctx.search(baseDN, filter, constraints);
if
(en
==
null
){
System.out.println(
"
There have no value
"
);
}
else
{
while
(en.hasMoreElements()){
Object obj
=
en.nextElement();
if
(obj
instanceof
SearchResult){
SearchResult sr
=
(SearchResult) obj;
String cn
=
sr.getName();
System.out.println(
"
cccccc:
"
+
cn);
}
}
}
}
catch
(javax.naming.AuthenticationException e){
System.out.println(e.getMessage());
}
catch
(Exception e){
System.out.println(
"
erro:
"
+
e);
}
}
}

于是又去跟abframe的代码,并重新检查文件,并查了一些关于LDAP验证参数的资料。终于可以验证,总结如下:
ldap验证有几个比较重要的参数:
ldap_base_provider_url, 
ldap服务器的地址及端口,如: ldap://192.168.1.1:389/
ldap_security_principal,  
用来查询验证ldap服务的用户
如 cn=uname,ou=pet,dc=abc,dc=com,或者有可能是cn=uadmin,cn=users,dc=abc,dc=com
这里是最最关键的地方,我也是在这方面花费了最多的时间,
如果服务器的域名是 abc.com 那么就要有 dc=abc,dc=com,其他情况以此类推
cn是指的用户名,但是这里有两种情况,一种是cn=uname,ou=pet,另一种是cn=uadmin,cn=users
我的猜测是如果在windows Active Directory的内建分组users下的用户则用第二种
如果是在windows Active Directory的自建分组,如组名为PET,则用第一种

dap_security_credentials,

用来查询验证ldap服务的密码,与ldap_security_principal配对 如 f34dgd
这里需要重点说明一下,ldap_security_principal与ldap_security_principal所指定的用户和密码并不是
最终要验证的用户,而是一个用来查询所要验证的用户是否存在的用户。
ldap_base_dn,             ldap服务的验证基址,因为ldap是基于目录,也就有层次关系,如ou=PET,dc=intasect,dc=local
这里是需要验证的用户目录,至于参数的解释同ldap_security_principal

ldap_auth_search_filter
查询验证用户的搜索条件,一般是(objectClass=person),是什么意思我也没细去研究
ldap_auth_method
身份验证方式, bind 或 password-compare
bind 基于绑定用户身份检查,我这里采用的第一种,也许是因为windows AD是这一种,另一种无法通过
password-compare 基于加密算法,采用密码比较方法
ldap_auth_password_encryption_algorithm
密码加密方法 MD5,SHA等。
我用的是MD5

以上参数错一个可能就通不过验证,所以参数的正确性是关键。

这里留下一些参考的资料

1,LDAP验证常见的错误代码

javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 52e, vece

意思是用户名或密码错误
javax.naming.NamingException: [LDAP: error code 1 - 00000000: LdapErr: DSID-0C090AE2, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, vece
大概是查询的目录无效,应该是ou设置错误

 

2,参考网站

 

3,windows active directory在win2003上的安装方法

其实安装AD的过程也就是把此机器升级为域控制器的过程,有一点要提醒的是在升级域之前一定要备份自建账户信息
否则当降级为普通计算机时所有自建账户信息将丢失。切记。

 

4,在ActiveDirectory新建组,新建用户,配置域名

希望有其他朋友遇到同样问题时少走弯路。

转载地址:http://nalgb.baihongyu.com/

你可能感兴趣的文章
Part 2 - Fundamentals(4-10)
查看>>
使用Postmark测试后端存储性能
查看>>
NSTextView 文字链接的定制化
查看>>
第五天站立会议内容
查看>>
CentOs7安装rabbitmq
查看>>
(转))iOS App上架AppStore 会遇到的坑
查看>>
解决vmware与主机无法连通的问题
查看>>
做好产品
查看>>
项目管理经验
查看>>
笔记:Hadoop权威指南 第8章 MapReduce 的特性
查看>>
JMeter响应数据出现乱码的处理-三种解决方式
查看>>
获取设备实际宽度
查看>>
图的算法专题——最短路径
查看>>
vue cli的安装与使用
查看>>
SQL批量删除与批量插入
查看>>
Notes on <High Performance MySQL> -- Ch3: Schema Optimization and Indexing
查看>>
C语言之一般树
查看>>
懂了很多大道理,却依旧过不好一生
查看>>
手工数据结构系列-C语言模拟队列 hdu1276
查看>>
【PyQt5 学习记录】008:改变窗口样式之二
查看>>