实验条件:
一台server2003作为证书服务器,域控制器以及AD服务器
服务器上需要安装server2003工具集,在安装包的SUPPORT/TOOLs文件夹下,SUPTOOLS.MSI为安装文件,然后找到工具集中的ldp.exe
一台客户机
实验步骤:
1. 在AD服务器上为客户机添加账号,设置密码以及相关信息
2. 在客户机登录该域账号后进入证书申请页面申请相应证书存储至系统或存储到智能卡
3. 通过ldap地址查找AD服务器上的用户对象(可用ldp工具进行查找测试),其中有一属性名为userCertificate,值为byte数组,我们可获取后将其转换为base64码,在需要使用时解码得到二进制数组并可转换成对应证书对象。
LDP工具查询演示:
1.Connection -> Connect 连接相应的域,Server为计算机名,Port默认为389
2.Connection -> Bind 绑定域账号
3. View -> Tree 查看LDAP指定节点(下图为指定节点的属性显示,可看见userCertificate属性)
下图为查询CRL分发点(CDP),可以看到CRL和deltaCRL

C#代码片段
//该函数主要用作查找当前对象的属性
private void GetChildren(DirectoryEntry entry, TreeNode entryNode)
{
PropertyCollection properties = entry.Properties;
foreach (string name in properties.PropertyNames)
{
//输出所有属性名及值
foreach (object o in properties[name])
{
//如果属性名为userCertificate 即用户证书属性
if (name == "userCertificate")
{
// entryNode.Nodes.Add(name + ": " + o.ToString());
Byte[] caCert_byte = o as Byte[];
string caCert_base = Convert.ToBase64String(caCert_byte);
entryNode.Nodes.Add(name + ": " + caCert_base);
}
//其他属性
else
{
entryNode.Nodes.Add(name + ": " + o.ToString());
}
}
}
}
//以下代码为ldap链接语句
using (DirectoryEntry root = new DirectoryEntry())
{
// root.Path = "LDAP://iss-b79167109c6:389/DC=iss,DC=whu";
//ldap地址,查找用户对象,也可从根目录DC=iss,DC=whu开始查找
root.Path = "LDAP://iss-b79167109c6:389/CN=CN_Name,CN=Users,DC=iss,DC=whu";
TreeNode node = new TreeNode(root.Name);
treeView1.Nodes.Add(node);
TreeNode node1 = new TreeNode("properties");
node.Nodes.Add(node1);
GetChildren(root, node1);
// this.treeView1.ExpandAll();
}
JAVA代码片段
import java.util.Enumeration;
import java.util.Hashtable;
import javax.naming.*;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
public class test {
/**
* @param args
*/
public static void main(String[] args) {
/*指定ldap链接参数及绑定账号密码*/
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://iss-b79167109c6:389");//链接地址
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL,
"CN=Administrator,CN=Users,DC=iss,DC=whu");//账号
env.put(Context.SECURITY_CREDENTIALS, "");//密码
try {
DirContext ctx = new InitialDirContext(env); //初始化上下文
SearchControls searchCons = new SearchControls(); //搜索控件
NamingEnumeration namingEnum = null;
searchCons.setSearchScope(SearchControls.SUBTREE_SCOPE);//SUBTREE_SCOPE
searchCons.setCountLimit(0);//设置最大返回个数
searchCons.setTimeLimit(0);//超时
//搜索对象,第一个参数为基目录,第二个参数为fiter,fiter格式可类似于(&(CN=*)(DC=*))
namingEnum = ctx.search("CN=Users,DC=iss,DC=whu", "(CN=CN_Name)", searchCons);
//遍历搜索结果
while (namingEnum.hasMore()) {
// Use debug to see the attributes
Object obj = namingEnum.nextElement();
SearchResult result = (SearchResult) obj;
//获取搜索结果对象的属性
NamingEnumeration attrs = result.getAttributes().getAll();
//遍历属性,将userCertificate的值转换为base64字符串输出
while(attrs.hasMore()){
Attribute attr = (Attribute)attrs.next();
if(attr.getID().endsWith("userCertificate"))
System.out.println((new sun.misc.BASE64Encoder()).encode((byte[])attr.get()));
}
System.out.println("--------------------------------------------");
//通过属性名称获取搜索结果对象的属性值
Attribute attr = result.getAttributes().get("userCertificate");
System.out.println((new sun.misc.BASE64Encoder()).encode((byte[])attr.get()));
}
} catch (NamingException e) {
e.printStackTrace();
}
}
}