- 论坛徽章:
- 0
|
跟踪Sun JNDI LDAP Service Provider底层通讯对Sun JNDI LDAP Service Provider底层与LDAP Server通讯进行跟踪,获取更多有用的debug信息。当然,很多情况下我们可以通过在服务器端,或者负载均衡服务器上使用tcpdump抓包,然后再使用类似ethereal的工具进行分析,可以获得直观清晰的数据。但是仍然有不足的地方:
1. 当用户没有服务器的适当权限,比如没有root身份不能执行tcpdump
2. 当分析工具不支持解析中文时,而数据包中又存在中文字符时 所以,通过Sun JNDI LDAP Service Provider,直接获取客户端和Server间的通讯信息,同时可以对中文进行支持,以满足特殊情况下的需要。
--
一般情况下,我们可以通过如下的设置来跟踪Sun JNDI LDAP Service Provider与LDAP Server通讯的情况:
Hashtable p= new Hashtable();
p.put( DirContext.PROVIDER_URL, "[url=]ldap://localhost:389[/url]");
p.put( DirContext.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
p.put( DirContext.SECURITY_CREDENTIALS, "directory");
p.put( DirContext.SECURITY_PRINCIPAL, "cn=Directory Manager");
p.put( "com.sun.jndi.ldap.trace.ber", System.out);
InitialDircontext ctx= new InitialDirContext( p);
然后我们进行LDAP相关的操作:
public static void main( String[] args) throws Exception {
DirContext ctx= null;
try {
ctx= getCtx();
SearchControls cons= new SearchControls();
cons.setSearchScope( 1);
NamingEnumeration enu= ctx.search( "dc=com", "objectclass=*", cons);
enu.close();
}catch ( NamingException ex) {
ex.printStackTrace();
}finally {
try {
if ( ctx!= null) ctx.close();
}catch ( Exception ex) {}
}
}
下面是默认的Hex格式输出:
-> localhost:389 0000: 30 29 02 01 01 60 24 02 01 03 04 14 63 6E 3D 44 0)...`$.....cn=D
0010: 69 72 65 63 74 6F 72 79 20 4D 61 6E 61 67 65 72 irectory Manager
0020: 80 09 64 69 72 65 63 74 6F 72 79 ..directory
<- localhost:389 0000: 30 0C 02 01 01 61 07 0A 01 00 04 00 04 00 0....a........
-> localhost:389 0000: 30 4F 02 01 02 63 2D 04 0D 64 63 3D 74 61 6E 6E 0O...c-..dc=tann
0010: 69 6E 2E 63 6F 6D 0A 01 01 0A 01 03 02 01 00 02 in.com..........
0020: 01 00 01 01 00 87 0B 6F 62 6A 65 63 74 63 6C 61 .......objectcla
0030: 73 73 30 00 A0 1B 30 19 04 17 32 2E 31 36 2E 38 ss0...0...2.16.8
0040: 34 30 2E 31 2E 31 31 33 37 33 30 2E 33 2E 34 2E 40.1.113730.3.4.
0050: 32 2
<- localhost:389 0000: 30 7F 02 01 02 64 7A 04 2A 63 6E 3D 44 69 72 65 0....dz.*cn=Dire
0010: 63 74 6F 72 79 20 41 64 6D 69 6E 69 73 74 72 61 ctory Administra
0020: 74 6F 72 73 2C 20 64 63 3D 74 61 6E 6E 69 6E 2E tors, dc=tannin.
0030: 63 6F 6D 30 4C 30 28 04 0B 6F 62 6A 65 63 74 43 com0L0(..objectC
0040: 6C 61 73 73 31 19 04 03 74 6F 70 04 12 67 72 6F lass1...top..gro
0050: 75 70 6F 66 75 6E 69 71 75 65 6E 61 6D 65 73 30 upofuniquenames0
0060: 20 04 02 63 6E 31 1A 04 18 44 69 72 65 63 74 6F ..cn1...Directo
0070: 72 79 20 41 64 6D 69 6E 69 73 74 72 61 74 6F 72 ry Administrator
0080: 73 s
-> localhost:389 0000: 30 23 02 01 03 50 01 02 A0 1B 30 19 04 17 32 2E 0#...P....0...2.
0010: 31 36 2E 38 34 30 2E 31 2E 31 31 33 37 33 30 2E 16.840.1.113730.
0020: 33 2E 34 2E 32 3.4.2
-> localhost:389 0000: 30 22 02 01 04 42 00 A0 1B 30 19 04 17 32 2E 31 0"...B...0...2.1
0010: 36 2E 38 34 30 2E 31 2E 31 31 33 37 33 30 2E 33 6.840.1.113730.3
0020: 2E 34 2E 32 .4.2
<- localhost:389 0000: 30 5B 02 01 02 64 56 04 18 6F 75 3D 47 72 6F 75 0[...dV..ou=Grou
0010: 70 73 2C 20 64 63 3D 74 61 6E 6E 69 6E 2E 63 6F ps, dc=tannin.co
0020: 6D 30 3A 30 28 04 0B 6F 62 6A 65 63 74 43 6C 61 m0:0(..objectCla
0030: 73 73 31 19 04 03 74 6F 70 04 12 6F 72 67 61 6E ss1...top..organ
0040: 69 7A 61 74 69 6F 6E 61 6C 75 6E 69 74 30 0E 04 izationalunit0..
0050: 02 6F 75 31 08 04 06 47 72 6F 75 70 73 .ou1...Groups
<- localhost:389 0000: 30 5B 02 01 02 64 56 04 18 6F 75 3D 50 65 6F 70 0[...dV..ou=Peop
0010: 6C 65 2C 20 64 63 3D 74 61 6E 6E 69 6E 2E 63 6F le, dc=tannin.co
0020: 6D 30 3A 30 28 04 0B 6F 62 6A 65 63 74 43 6C 61 m0:0(..objectCla
0030: 73 73 31 19 04 03 74 6F 70 04 12 6F 72 67 61 6E ss1...top..organ
0040: 69 7A 61 74 69 6F 6E 61 6C 75 6E 69 74 30 0E 04 izationalunit0..
0050: 02 6F 75 31 08 04 06 50 65 6F 70 6C 65 .ou1...People
<- localhost:389 0000: 30 81 9B 02 01 02 64 81 95 04 1E 6F 75 3D 53 70 0.....d....ou=Sp
0010: 65 63 69 61 6C 20 55 73 65 72 73 2C 64 63 3D 74 ecial Users,dc=t
0020: 61 6E 6E 69 6E 2E 63 6F 6D 30 73 30 28 04 0B 6F annin.com0s0(..o
0030: 62 6A 65 63 74 43 6C 61 73 73 31 19 04 03 74 6F bjectClass1...to
0040: 70 04 12 6F 72 67 61 6E 69 7A 61 74 69 6F 6E 61 p..organizationa
0050: 6C 55 6E 69 74 30 15 04 02 6F 75 31 0F 04 0D 53 lUnit0...ou1...S
0060: 70 65 63 69 61 6C 20 55 73 65 72 73 30 30 04 0B pecial Users00..
0070: 64 65 73 63 72 69 70 74 69 6F 6E 31 21 04 1F 53 description1!..S
0080: 70 65 63 69 61 6C 20 41 64 6D 69 6E 69 73 74 72 pecial Administr
0090: 61 74 69 76 65 20 41 63 63 6F 75 6E 74 73 ative Accounts
<- localhost:389 0000: 30 0C 02 01 02 65 07 0A 01 00 04 00 04 00 0....e........
我们虽然取到了底层通讯的数据,但是根本无法直接阅读,因此有两种方法可以输出符合我们习惯的内容:
1. 通过反编译Sun的class文件,来获取LDAPMessage格式的输出
2. 增加一个FilterOutputStream,对Sun输出的内容进行处理,处理后输出LDAPMessage格式的内容
两种方法都可以实现,但是第二种性能很差,Sun既要花时间格式化成Hex格式,我们还要在FilterOutputStream中反其道而行之,重新恢复成原始数据,然后再解析,过程中涉及到大量的String - byte[] 操作,因此性能比较差。但是不像第一种,第一种应该是一种违法的行为。
按照我们的要求格式化后的输出如下:
-> localhost:389 LDAPMessage {
messageID = 1,
protocolOp = {
bindRequest = {
version = 3,
name = cn=Directory Manager,
authentication = {
simple = directory }
}
} }
<- localhost:389 LDAPMessage {
messageID = 1,
protocolOp = {
bindResponse = {
resultCode = 0,
matchedDN = ,
errorMessage =
}
} }
-> localhost:389 LDAPMessage {
messageID = 2,
protocolOp = {
searchRequest = {
baseObject = dc=tannin.com,
scope = 1,
derefAliases = 3,
sizeLimit = 0,
timeLimit = 0,
typesOnly = false,
filter = {
present = objectclass },
attributes = {
}
}
}
,
controls = {
{
controlType = 2.16.840.1.113730.3.4.2,
criticality = false
}
}
}
<- localhost:389 LDAPMessage {
messageID = 2,
protocolOp = {
searchResEntry = {
objectName = cn=Directory Administrators, dc=tannin.com,
attributes = {
{
type = objectClass,
vals = {
top,
groupofuniquenames
}
},
{
type = cn,
vals = {
Directory Administrators
}
}
}
} } }
-> localhost:389 LDAPMessage {
messageID = 3,
protocolOp = {
abandonRequest = 2 }
,
controls = {
{
controlType = 2.16.840.1.113730.3.4.2,
criticality = false
}
}
}
<- localhost:389 LDAPMessage {
messageID = 2,
protocolOp = {
searchResEntry = {
objectName = ou=Groups, dc=tannin.com,
attributes = {
{
type = objectClass,
vals = {
organizationalunit,
top
}
},
{
type = ou,
vals = {
Groups
}
}
}
} } }
-> localhost:389 LDAPMessage {
messageID = 4,
protocolOp = {
unbindRequest = NULL }
,
controls = {
{
controlType = 2.16.840.1.113730.3.4.2,
criticality = false
}
}
}
- 由于LDAP协议规定,LDAP Message是符合ASN.1 BER规则的字节流,但是我们没有必要自己来实现Ber Encoder/Decoder。我使用了很早以前IBM的Snacc for Java,它可以自动根据LDAP V3 ASN Definitions来生成Java类文件,然后使用它的Encoder/Decoder就可以处理了。由于IBM已经移除了Snacc,并且已经不再是免费的软件,所以使用上受到限制。OpenSource正有几个Project关于ASN Compiler的,但是还不够成熟,相信不久的将来就可以取代Snacc。
- 从上面的Trace中也可以看出,Sun在处理NamingEnumeration.close()处有一个缺陷,即当对一个NamingEnumeration实例在没有完成全部遍历时,执行close()操作会导致Sun LDAP SP 向LDAP Server发送一个LDAP Abandon Request。因此我们需要在即使只有一个返回值的情况下也要完成遍历,或者干脆不关闭NamingEnumeration来避免这种情况。
|
|