实例化DirContext的时候报了AuthenticationException,错误码为49

[+]
这篇博文的原因

主要是因为犯了一个很愚蠢的错误,在实例化DirContext的时候报了AuthenticationException,错误码为49,我很疑惑,同样的方式通过ldapBrowser可以连接,在JNDI却不能连接了,同样尝试了Java的Apache Directory Studio插件也是不能连接,但是匿名连接却连接得上。基于这个原因便开始了探究初始化过程的分析,不过最后的结论却是——只是我的principal错了而已,我一直以为是我的credentials的问题。为什么同样用cn=Manager通过LDAPBrowser能访问,而通过JNDI或者ADS插件却不能访问呢?理由(大概)是访问的时候完整的用户dn应该都是cn=Manager,dc=maxcrc,dc=com,这个你定义在slap.conf的rootDn,而为什么ldapBrowser能够通过cn=Manager来访问呢?那是因为它有进行了一些拼接,因此我们总以为A是这样所以B应该是这样的想法有时候不一定通用,特别是当它们属于两个不同的项目的时候。虽然这样一来分析源码的意义不存在了,但是还是把分析过程贴出来和大家分享分享,过程也是比较简略,而且针对一种情况分析。

分析过程

该分析过程建立于以下基础:

evn.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");//导入提供者
evn.put(Context.PROVIDER_URL, "ldap://localhost/dc=maxcrc,dc=com");//服务器地址
evn.put(Context.SECURITY_AUTHENTICATION, "simple");//验证方式
在getInitialContext中主要操作如下:

...
//获取ldapURL
String str = paramHashtable != null ? (String)paramHashtable.get("java.naming.provider.url") : null;

...
//切割成string数组
arrayOfString = LdapURL.fromList(str);

...
//获取LdapCtx实例

11
getLdapCtxInstance如下:

{
if ((paramObject instanceof String)
www.chuangyed.com)
return getUsingURL((String)paramObject, paramHashtable);
if ((paramObject instanceof String[])) {
return getUsingURLs((String[])paramObject, paramHashtable);

因为我们是数组,所以这里调用的是第二个函数:

...

for (int i = 0; i < paramArrayOfString.length; www.zhuyingyule.cn i++) {
try {
return getUsingURL(paramArrayOfString[i], paramHashtable);
} catch ...

说实话我也不明白他为什么这么操作,它被URL切割成数组后实际上也只有一个值,因为它是根据“ ”切割的,而这里即使有多个值它也只处理一个值,讲道理我实在不明白,是为了代码健壮性?
getUsingURL这个方法名我们可以理解成通过URL获取目录服务上下文,现在进入它的方法体:

...
localObject = new LdapCtx(str1, str2, i, paramHashtable, localLdapURL.useSsl());

它主要是调用了这个方法,其中str1是DN,str2是host,i是port,paramHashtable是环境变量,不过已经经过了一些操作,useSsl返回true或false,它表示是否通过ssl验证,我们这里只是简单验证,因此为false.
LdapCtx的构造函数如下定义:

...
if ("ssl".equals(this.envprops.get("java.naming.security.protocol"))) {
this.useSsl = true;
}

我们可以看到,假如我们通过ssl验证的话,那我们给环境变量加上java.naming.security.protocol这个属性,并设值为ssl。此外在这里进行了设值操作,并且调用initEvn把所有的值设进去,initEvn如下:

http://blog.sina.com.cn/u/5080116125
private void initEnv() throws NamingException {
/* 2330 */ if (this.envprops == null)
/* */ {
/* 2332 */ setReferralMode(null, false);
/* 2333 */ return;
/* */ }
/* */
/* */
/* 2337 */ setBatchSize((String)this.envprops.get("java.naming.batchsize"));
/* */
/* */
/* 2340 */ setRefSeparator((String)this.envprops.get("java.naming.ldap.ref.separator"));www.aboyule.org
/* */
/* */
/* 2343 */ setDeleteRDN((String)this.envprops.get("java.naming.ldap.deleteRDN"));
/* */
/* */
/* 2346 */ setTypesOnly((String)this.envprops.get("java.naming.ldap.typesOnly"));
/* */
/* */
/* 2349 */ setDerefAliases((String)this.envprops.get("java.naming.ldap.derefAliases"));
/* */
/* */
/* 2352 */ setReferralLimit((String)this.envprops.get("java.naming.ldap.referral.limit"));
/* */
/* 2354 */ setBinaryAttributes((String)this.envprops.get("java.naming.ldap.attributes.binary"));
/* */
/* 2356 */ this.bindCtls = cloneControls((Control[])this.envprops.get("java.naming.ldap.control.connect"));
/* */
/* */
/* 2359 */ setReferralMode((String)this.envprops.get("java.naming.referral"), false);
/* */
/* */
/* 2362 */ setConnectTimeout((String)this.envprops.get("com.sun.jndi.ldap.connect.timeout"));
/* */
/* */
/* 2365 */ setReadTimeout((String)this.envprops.get("com.sun.jndi.ldap.read.timeout"));
/* */
/* */
/* */
/* 2369 */ setWaitForReply((String)this.envprops.get("com.sun.jndi.ldap.search.waitForReply"));
/* */
/* */
/* 2372 */ setReplyQueueSize((String)this.envprops.get("com.sun.jndi.ldap.search.replyQueueSize"));
/* */ }
1
它是判断你是不是v3版本的ldap,v3的字符编码和v2的不一样,因此进行了不同的编码转化,那么我们可以猜测,认证失败可能是因为版本的问题,等会儿如果我们还是找不到关键的问题所在的话我们应该试一下两个版本。

到这里解读结束,对于认证的解读有些简略,说实话这部分我也很混乱,大致的过程似乎是通过我们给定的账号去请求一个请求信息,然后看它怎么回应,如果成功就会回应一个ldap操作对象给我们,大概是这样吧。如果不去细究认证的细节的话,我们仅仅需要知道它尝试去认证了,之后获得一个保存结果的对象,在processReturnCode这个方法里面对这个状态码进行判断,认证成功状态码为0,我们这里认证失败,而且是用户名不正确则是抛出49的错误,如果认证失败则在这里负责把之前开启的资源关闭。其实如果我好好去看JNDI的文档或者好好细读ADS的文档大概就没这么多事了,懒人真的屎尿多。

时间: 2025-01-08 05:42:51

实例化DirContext的时候报了AuthenticationException,错误码为49的相关文章

python安装程序是报这样的错UnicodeDecodeError: &#39;ascii&#39; codec can&#39;t decode byte 0xb0 in position 1: ordinal not in range(128)

python在安装时,默认的编码是ascii,当程序中出现非ascii编码时,python的处理常常会报这样的错UnicodeDecodeError: 'ascii' codec can't decode byte 0x?? in position 1: ordinal not in range(128) 有2种方法设置python的默认编码: 方法一: 在程序中加入以下代码: import sys reload(sys) sys.setdefaultencoding('utf8') 方法二:

iOS真机测试友盟碰到错误linker command failed with exit code 1 (use -v to see invocation) 百度地图的检索失败 sqlite 错误码

因为友盟不支持bitcode 在模拟器上运行正常,但是在模拟器上就会报错,这是因为xocde7之后增加了一个bitcode,bitcode是被编译程序的一种中间形式的代 码.包含bitcode配置的程序将会在App store上被编译和链接.bitcode允许苹果在后期重新优化程序的二进制文件,而不需要重新提交一个新的版本到App store上. 碰到以上问题,我们有两种解决方式,要么关闭bitcode要么让第三方支持bitcode,我们这里讲第一种,配置bitcode,我们可以 在”Build

GetLastError错误码大全

GetLastError返回的值通过在api函数中调用SetLastError或SetLastErrorEx设置.函数 并无必要设置上一次错误信息,所以即使一次GetLastError调用返回的是零值,也不能 担保函数已成功执行.只有在函数调用返回一个错误结果时,这个函数指出的错误结果 才是有效的.通常,只有在函数返回一个错误结果,而且已知函数会设置GetLastError 变量的前提下,才应访问GetLastError:这时能保证获得有效的结果.SetLastError函 数主要在对api函数

彻底解决ASP.NET MVC 3 404错误码返回302的问题

转自:http://blog.csdn.net/mycloudke/article/details/9746333 404状态码:,意味着当在页面上显示用户点击不存在,提高用户体验度,搜索引擎会放弃这个页面索引. 302状态码:搜索引擎将继续指数,这将导致大量不同的链接指向同一个页面,它将影响搜索引擎对站点的信任度. http://www.cloudke.com.cn/ 后面随便带些参数或者不存在的文件名,然后跳转到自定义错误页,但返回的状态是302. 解决办法: 第一步: 将web.confi

ORACLE.错误码&#160;ORA-12154 及Oracle客户端免安装版的设置

.错误码 ORA-12154相信作为ORACLE数据库的开发人员没有少碰到“ORA-12154: TNS: 无法解析指定的连接标识符”,今天我也又碰到了类似的情况,将我的解决方法进行小结,希望能对碰到同样问题的友人们提供帮助.问题场景描述:服务器端版本:oracle 10.2.0.10客户端版本:oracle 10.2.0.10客户端开发工具:PL/SQL Developer通过客户端来连接服务器,其主要文件就是通过客户端的tnsnames.ora来配置,在原文件的基础上增加:SID别名 =  

Android基础入门教程——7.5.6 WebView处理网页返回的错误码信息

Android基础入门教程--7.5.6 WebView处理网页返回的错误码信息 标签(空格分隔): Android基础入门教程 本节引言: 嘿嘿,假如你们公司是做HTML5端的移动APP的,就是通过WebView来显示网页的,假如你访问的网页 不存在,或者其他错误,报404,401,403,30X等错误的状态码,如果直接弹出WebView默认的错误 提示页面,可能显得不那么友好,我们可以重写WebViewClient的onReceivedError()方法来实现我们 想要的效果,一般的做法有两

UTF-8,Unicode,GBK,希腊字母读法,ASCII码表,HTTP错误码,URL编码表,HTML特殊字符,汉字编码简明对照表

UNICODE,GBK,UTF-8区别 UNICODE,GBK,UTF-8区别    简单来说,unicode,gbk和大五码就是编码的值,而utf-8,uft-16之类就是这个值的表现形式.而前面那三种编码是一兼容的,同一个汉字,那三个码值是完全不一样的.如"汉"的uncode值与gbk就是不一样的,假设uncode为a040,gbk为b030,而uft-8码,就是把那个值表现的形式.utf-8码完全只针对uncode来组织的,如果GBK要转UTF-8必须先转uncode码,再转utf-8就O

CMPP错误码说明

与中国移动代码的对应关系. MI::zzzzSMSC返回状态报告的状态值为EXPIREDMJ:zzzzSMSC返回状态报告的状态值为DELETEDMK:zzzzSMSC返回状态报告的状态值为UNDELIVML:zzzzSMSC返回状态报告的状态值为ACCEPTDMM:zzzzSMSC返回状态报告的状态值为UNKNOWNMN:zzzzSMSC返回状态报告的状态值为REJECTD 回页首 CMPP发送失败代码对照表 值(4位,不足4位前面补0) 含义1 消息结构错2 命令字错误3 消息序列号重复4

[译]libcurl错误码

CURLcode Almost all "easy" interface functions return a CURLcode error code. No matter what, using the curl_easy_setopt option CURLOPT_ERRORBUFFER is a good idea as it will give you a human readable error string that may offer more details about