为 OTN 撰稿
为 Oracle 技术网撰写技术文章,获得报酬的同时可提升技术技能。
更多信息
密切关注
OTN 架构师社区
OTN ArchBeat 博客 Facebook Twitter YouTube 随身播图标

诊断 Oracle WebLogic 中的间歇性身份验证失败和用户锁定

作者:Shailesh K. Mishrah

如何使用现有的调试标志和日志文件诊断 WebLogic 中的登录失败。

2014 年 2 月

下载
download-icon13-1Oracle WebLogic

简介

Oracle WebLogic Server 中的身份验证失败可能有多种原因。总是发生失败时,如果您了解 WebLogic 中的身份验证执行方式,调试和修复就比较容易了。但如果失败是间歇性的,事情就有点棘手了。本文介绍为诊断间歇性身份验证失败而必须启用的调试以及应查阅的日志文件,尤其是使用外部系统(如轻型目录访问协议 (LDAP))为 WebLogic 配置身份验证时。本文还讨论了 WebLogic 中由于此类间歇性身份验证失败而导致用户帐户被软锁定的情况,如何验证帐户软锁定和如何解锁。

本文源于一个最近的客户案例:Oracle Identity Manager (OIM) API 因 WebLogic 中的身份验证失败而开始间歇性失败。本文假定读者充分了解 WebLogic 安全概念和身份验证机制。本文使用了 WebLogic 10.3.6 版。

了解 WebLogic 中的身份验证流程

WebLogic 使用身份验证提供程序证明给定凭证是否正确。WebLogic Security Framework 支持对一个安全领域使用多个身份验证提供程序;这些身份验证提供程序的配置(每个提供程序的 Java 身份验证和授权服务 (JAAS) 控制标志的值)会影响身份验证过程的总体结果。下面列出了 JAAS 控制标志值以及它们如何控制整个身份验证过程(更多详细信息,请参见参考资料部分):

  • REQUIRED:始终调用身份验证提供程序,且用户始终必须通过身份验证测试。无论身份验证成功与否,都会继续执行列表中的下一个提供程序。
  • REQUISITE:用户必须通过该身份验证提供程序的身份验证测试。如果用户通过验证,执行后续提供程序,但可能会失败(JAAS 控制标志设置为 REQUIRED 的身份验证提供程序除外)。
  • SUFFICIENT:用户不必通过该身份验证提供程序的身份验证测试。如果身份验证成功,不执行后续身份验证提供程序。如果身份验证失败,继续执行列表中的下一个提供程序。
  • OPTIONAL:允许用户通过或不通过该身份验证提供程序的身份验证测试。但如果安全领域中配置的所有身份验证提供程序的 JAAS 控制标志均设置为 OPTIONAL,则用户必须通过其中一个已配置的提供程序中的身份验证测试。

如 REQUIRED 控制标志的说明部分所示,带该标志的身份验证提供程序必须通过身份验证,否则即使提供的凭证正确,最终用户身份验证也会失败;其原因包括网络问题、与该身份验证提供程序对话的外部系统(如 LDAP)的异常行为等。

启用安全调试了解情况

开始发现登录失败时,首先要做的是启用 WebLogic 中的安全调试;在请求可能到达的所有服务器上(即负载平衡器 t3 url (t3://host1:port1,host2:port2) 中配置的所有服务器上)均需如此。此设置对每个服务器均有效。要启用安全调试,请执行以下步骤:

  1. 转到 Servers > server_Instance
  2. 选择 WebLogic > Security > atn > DebugSecurityAtn
  3. 单击 Enable 按钮。

此更改无需重新启动服务器。一旦启用该标志,WebLogic 就开始将调试信息加入服务器日志文件中。以下是一次成功登录的示例输出,其中的安全领域配置了一个默认的身份验证程序:

####<Jan 11, 2014 8:40:44 PM IST> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <>
<1389453044555> <BEA-000000> 
<com.bea.common.security.internal.service.CallbackHandlerWrapper.handle got username from 
callbacks[0], UserName=weblogic> 
####<Jan 11, 2014 8:40:44 PM IST> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
 ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <>
  <1389453044555> <BEA-000000> <LDAP Atn Login username: weblogic> 
####<Jan 11, 2014 8:40:44 PM IST> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
 ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <>
  <1389453044555> <BEA-000000> <authenticate user:weblogic> 
####<Jan 11, 2014 8:40:44 PM IST> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
 ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <>
  <1389453044555> <BEA-000000> <getConnection return conn:LDAPConnection 
  { ldapVersion:2 bindDN:""}> 
####<Jan 11, 2014 8:40:44 PM IST> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
 ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <>
  <1389453044555> <BEA-000000> <getDNForUser search
  ("ou=people,ou=myrealm,dc=WLS_A",
   "(&(uid=weblogic)(objectclass=person))", base DN & below)> 
####<Jan 11, 2014 8:40:44 PM IST> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
 ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <>
  <1389453044556> <BEA-000000> <DN for user weblogic: uid=weblogic,
  ou=people,ou=myrealm,dc=WLS_A> 
####<Jan 11, 2014 8:40:44 PM IST> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
 ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <>
  <1389453044556> <BEA-000000> <returnConnection conn:LDAPConnection 
  { ldapVersion:2 bindDN:""}> 
####<Jan 11, 2014 8:40:44 PM IST> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
 ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <>
  <1389453044556> <BEA-000000> <authenticate user:weblogicwith DN:uid=weblogic,
  ou=people,ou=myrealm,dc=WLS_A> 
####<Jan 11, 2014 8:40:44 PM IST> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
 ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <>
  <1389453044556> <BEA-000000> <getConnection return conn:LDAPConnection 
  { ldapVersion:2 bindDN:""}> 
####<Jan 11, 2014 8:40:44 PM IST> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
 ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <>
  <1389453044556> <BEA-000000> <authentication succeeded> 
####<Jan 11, 2014 8:40:44 PM IST> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
 ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <>
  <1389453044556> <BEA-000000> <returnConnection conn:LDAPConnection 
  { ldapVersion:2 bindDN:""}> 
####<Jan 11, 2014 8:40:44 PM IST> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
 ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <>
  <1389453044556> <BEA-000000> <LDAP Atn Authenticated User weblogic>

以下是一次失败登录的示例输出,其中的安全领域配置了一个 LDAP 身份验证程序,因 LDAP 连接问题而发生失败:

####<Jun 5, 2013 11:07:25 PM PDT> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> 
<[ACTIVE] ExecuteThread: '2' for queue:  'weblogic.kernel.Default (self-tuning)'> 
<<WLS Kernel>> <> <5b0dc9d8a952b6d1:-1eccb494:13f1505b73b:-8000-000000000001c5b1> 
<1370498845643> <BEA-000000> 
<new LDAP connection to host  SHAIMISH-LAP port 3061 use local connection is false> 
 . 
 ####<Jun 5, 2013 11:07:25 PM PDT> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> 
 <[ACTIVE] ExecuteThread: '2' for queue:  'weblogic.kernel.Default (self-tuning)'> 
 <<WLS Kernel>> <> <5b0dc9d8a952b6d1:-1eccb494:13f1505b73b:-8000-000000000001c5b1> 
 <1370498845644> <BEA-000000> 
 <created new LDAP connection LDAPConnection {  ldapVersion:2 bindDN:""}> 
 . 
 ####<Jun 5, 2013 11:07:25 PM PDT> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> 
 <[ACTIVE] ExecuteThread: '2' for queue:  'weblogic.kernel.Default (self-tuning)'> 
 <<WLS Kernel>> <> <5b0dc9d8a952b6d1:-1eccb494:13f1505b73b:-8000-000000000001c5b1> 
 <1370498845673> <BEA-000000> 
 <connection failed netscape.ldap.LDAPException:n Server or network error (81); 
 Cannot contact LDAP server> 
 . 
 ####<Jun 5, 2013 11:07:25 PM PDT> <Debug> <SecurityAtn> <SHAIMISH-LAP><AdminServer> 
 <[ACTIVE] ExecuteThread: '2' for queue:  'weblogic.kernel.Default (self-tuning)'> 
 <<WLS Kernel>> <> <5b0dc9d8a952b6d1:-1eccb494:13f1505b73b:-8000-000000000001c5b1> 
 <1370498845673> <BEA-000000> <[Security:090294]could not get connection>

遗憾的是,失败的原因并不总是这么清楚。例如,以下输出(来自一个配置了 LDAP 身份验证程序的安全领域的间歇性登录失败案例)并未清楚地显示错在何处:

####<Oct 7, 2013 12:44:21 PM EDT> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
ExecuteThread: '246' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <>
<d99500ee4d4904e8:1daa9ea9:14193a06acc:-8000-0000000000072676> <1381164261368> <BEA-000000>
<[Security:090295]caught unexpected exception> 
.................................................................................................
####<Oct 7, 2013 12:44:21 PM EDT> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
ExecuteThread: '246' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <>
<d99500ee4d4904e8:1daa9ea9:14193a06acc:-8000-0000000000072676> <1381164261368> <BEA-000000> 
<com.bea.common.security.internal.service.LoginModuleWrapper.commit delegated, returning false>
####<Oct 7, 2013 12:44:21 PM EDT> <Debug> <SecurityAtn> <SHAIMISH-LAP> <AdminServer> <[ACTIVE]
ExecuteThread: '246' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <>
<d99500ee4d4904e8:1daa9ea9:14193a06acc:-8000-0000000000072676> <1381164261368> 
<BEA-000000> <weblogic.security.service.internal.WLSJAASLoginServiceImpl$ServiceImpl.authenticate 
authenticate failed for user TESTCCOUNT>

在此类情况下,对于现成的 WebLogic LDAP 身份验证程序,请查看域目录下的 ldap_trace.logATN 日志文件。该文件包含有关 LDAP 通信到底发生了什么情况的信息。在上述场景中,该日志文件显示 LDAP 服务器出现了连接中断问题。

将失败异常传播到调用方(适用于同一 JVM 中运行的调用方)

对于在 WebLogic 中运行并以编程方式登录的代码,实际失败原因可通过现成的 WebLogic 身份验证程序传播到调用方。身份验证程序的 Provider Specific 选项卡中有一个名为 Propagate Cause For Login Exception 的标志(图 1),如果选中该标志,会将登录异常的实际原因传播到调用方,如下图所示。这有助于快速诊断以编程方式登录失败的问题。

mishra-wls-auth-fig01
图 1:传播登录异常原因

帐户软锁定

帐户软锁定是 WebLogic 中的一种防止针对用户帐户的拒绝服务 (DoS) 攻击的机制。例如,如果已知用户帐户登录,则有人可能多次尝试无效登录,导致该帐户在管理帐户的后端系统(如 LDAP)中被永久锁定。而真正的用户却因为帐户锁定而无法登录。为了防止这种情况,WebLogic 提供了一个帐户软锁定特性,启用该特性时,如果在 t2 时间间隔内出现 n 次无效登录尝试,则在 WebLogic 运行时本身中将帐户锁定 t1 时间 ,其中,t1、t2 和 n 可配置。一旦帐户在 WebLogic 运行时中被软锁定,就不会尝试向后端系统验证帐户凭证,从而防止该帐户被永久锁定。

尽管这个特性非常有用,但有时可能会导致很棘手的情况(尤其是出现间歇性登录失败时)。假设在应用中配置了一个服务帐户用于某个计划的服务,该服务运行非常频繁。该服务启动时,将检索服务帐户凭证并尝试以编程方式登录。如果此登录失败多次,WebLogic 运行时会将该帐户软锁定,导致该计划服务的情况更糟:即使登录失败的原因消失,也无法登录。唯一的解决办法是手动停止服务并解除对服务帐户的软锁定。

(在我看来,永远不应将服务凭证存储在系统中,因为这会导致帐户生命周期管理问题。例如,如果该帐户更改密码,就必须同时在存储密码的所有位置进行更改,否则就会导致失败。在这些情况下,我更喜欢使用身份断言,它只需提供帐户的用户 id。有关如何在 WebLogic 中使用 OPSS 执行身份断言的信息,请参见参考资料部分)。

下一节介绍一种在 WebLogic 中配置帐户软锁定的情况,以及如何使用 UserLockoutManager 解除该锁定。

WebLogic 软锁定配置和管理器

导航到 Security > realm name > User lockout,可查看软锁定配置,如下图所示

mishra-wls-auth-fig02
图 2:软锁定配置

您还可以导航到 Servers > Server Name > Monitoring > Security 查看特定 WebLogic 服务器实例出现无效登录的统计信息,如下图所示:

mishra-wls-auth-fig03
图 3:无效登录统计信息

为了手动解除帐户软锁定,WebLogic 提供了一个 UserLockoutManager mBean,它具有 isLockedOutclearLockout 方法。这两个方法将用户登录 ID 作为参数。调用 clearLockout 方法解除帐户软锁定。您可以调用 isLockedOut 方法检查帐户是否被软锁定。

mishra-wls-auth-fig04
图 4:帐户软锁定状态

总结

本文介绍了如何使用现有的调试标志和日志文件诊断 WebLogic 中的登录失败。由于性能原因,不要启用此调试日志程序;一旦身份验证问题得到确诊,请立即关闭此标志。本文还显示了间歇性登录失败如何导致 WebLogic 中帐户被软锁定,以及如何使用 UserLockoutManager mBean 解除此类软锁定。

参考资料

  1. 身份验证提供程序:http://docs.oracle.com/cd/E23943_01/web.1111/e13718/atn.htm
  2. 配置身份验证提供程序:http://docs.oracle.com/cd/E29542_01/web.1111/e13707/atn.htm
  3. 使用 Oracle Platform Security Services (OPSS) 执行编程身份断言:http://www.oracle.com/technetwork/cn/articles/idm/mishra-id-opss-2088117-zhs.html

作者感谢 Shaun Pei 对身份验证程序相关问题进行诊断分类的帮助。

关于作者

Shailesh K. Mishrah 是 Oracle Identity Manager 团队成员。他获得了印度理工学院的技术学士学位,闲暇之余,他喜欢研究中间件性能和安全。