多个 LDAP 服务器之间的安全性故障转移
可以配置 WebSphere® Application Server 安全性,以尝试在多个轻量级目录访问协议 (LDAP) 主机之间进行故障转移。
如果当前的活动 LDAP 服务器不可用,那么 WebSphere Application Server 安全性会尝试故障转移到指定主机列表中的第一个可用 LDAP 主机。多个 LDAP 服务器可以作为同一主控 LDAP 服务器的备用服务器,它们也可以是具有相同模式的任何 LDAP 主机,该模式包含从同一“LDAP 数据交换格式”(LDIF) 文件中导入的数据。
每当进行故障转移时,WebSphere Application Server 安全性始终会使用指定主机列表中的第一个可用 LDAP 服务器。例如,如果配置了四个 LDAP 服务器(顺序为 L1、L2、L3 和 L4),那么会将 L1 当作主要 LDAP 服务器。连接的优先顺序是从 L1 到 L4。例如,如果 WebSphere Application Server 安全性当前与 L4 相连,并且需要进行故障转移或重新连接,那么 WebSphere Application Server 安全性将首先尝试连接至 L1、L2,然后再尝试连接至 L3,直到连接成功为止。
当前 LDAP 主机名记录在 WebSphere Application Server 日志文件 SystemOut.log 中的 SECJ0419I 消息中。如果想重新连接至主要 LDAP 主机,那么在将 null,null 作为输入的情况下运行 WebSphere Application Server MBean 方法 resetLDAPBindInfo。
要在多个 LDAP 主机之间配置 LDAP 故障转移,必须使用 wsadmin 或 ConfigService 来包括任意数目的备用 LDAP 主机。显示在管理控制台中的 LDAP 主机就是主要 LDAP 主机,并且是 security.xml 中的 LDAP 主机列表中列示的第一项。
WebSphere Application Server 安全性领域名的缺省值为管理控制台中显示的主要 LDAP 主机名。它包含一个结尾冒号,如果存在端口号,那么还会包含一个端口号。但是,可以添加定制属性 com.ibm.websphere.security.ldap.logicRealm 以覆盖缺省安全领域名。使用 logicRealm 名称来将每个单元配置为具有它自己的 LDAP 主机,从而实现互操作性和向后兼容性,并且使它们能够灵活地动态添加或移除 LDAP 主机。如果从先前安装进行迁移,那么在再次启用了管理安全性之后,新的 logicRealm 名称才会生效。为了与不支持逻辑领域的前发行版兼容,logicRealm 名称必须与先前安装使用的名称相同(LDAP 主机名,包括结尾冒号和端口号)。
通过使用负载均衡器(它透明地转换为 WebSphere Application Server)将单个主机名与多个 IP 地址相关联来配置 LDAP 故障转移时,输入无效密码会导致多次重试 LDAP 绑定。WebSphere Application Server 将重试,负载均衡器会将请求传递到多个副本。使用缺省设置时,LDAP 绑定重试次数等于关联的 IP 地址数目加 1。这意味着单次无效登录尝试会导致 LDAP 帐户锁定。如果 com.ibm.websphere.security.registry.ldap.singleLDAP 定制属性设置为 false,那么将不重试 LDAP 绑定调用。
当通过使用 wsadmin 命令注册后端 LDAP 服务器主机名来配置 LDAP 故障转移时,请将 com.ibm.websphere.security.ldap.retryBind 属性设置为 false。
#---------------------------------------------------------------
# Main
# This is a bi-modal script: it can be included in the wsadmin
# command invocation like this:
# wsadmin -f LDAPAdd.jacl ldaphost 800
#
# or the script can be sourced from the wsadmin command line:
# wsadmin> source LDAPAdd.jacl
# wsadmin> LDAPAdd ldaphost 800
#
# The script expects some parameters:
# arg1 - LDAP Server host name
# arg2 - LDAP Server port number
#---------------------------------------------------------------
if { !($argc == 2)} {
puts ""
puts "LDAPAdd: This script requires 2 parameters: LDAP server host name and LDAP server port number"
puts "For example: LDAPAdd ldaphost 389"
puts ""
return;
}
else {
set ldapServer [lindex $argv 0]
set ldapPort [lindex $argv 1]
LDAPAdd $ldapServer $ldapPort
return;
}
proc LDAPAdd {ldapServer ldapPort args} {
global AdminConfig AdminControl ldapServer ldapPort
set ldapServer lindex $args 0
set ldapPort lindex $args 1
global ldapUserRegistryId
# Get the LDAP user registry object from the security configuration
if { catch {$AdminConfig list LDAPUserRegistry} result } {
puts stdout "\$AdminConfig list LDAPUserRegistry caught an exception $result\n"
return
}
else {
if {$result != {}} {
set ldapUserRegistryId lindex $result 0
}
else {
puts stdout "\$AdminConfig list LDAPUserRegistry caught an exception $result\n"
return;
}
}
# Set the host and port values in Attrs2
set Attrs2 list list hosts list list list host
$ldapServer
list port $ldapPort
# Modify the LDAP configuration host object
$AdminConfig modify $ldapUserRegistryId $Attrs2
$AdminConfig save
}
#---------------------------------------------------------------
# Add ldap hostname and port
# wsadmin -f LDAPAdd.py arg1 arg2
#
# The script expects some parameters:
# arg1 - LDAP Server hostname
# arg2 - LDAP Server portnumber
#---------------------------------------------------------------
import java
#-------------------------------------------------------
# get the line separator and use to do the parsing
# since the line separator on different platform are different
lineSeparator = java.lang.System.getProperty('line.separator')
#-------------------------------------------------------------------------------
# add LDAP host
#-------------------------------------------------------------------------------
def LDAPAdd (ldapServer, ldapPort):
global AdminConfig, lineSeparator, ldapUserRegistryId
try:
ldapObject = AdminConfig.list("LDAPUserRegistry")
if len(ldapObject) == 0:
print "LDAPUserRegistry ConfigId was not found\n"
return
ldapUserRegistryId = ldapObject.split(lineSeparator)[0]
print "Got LDAPUserRegistry ConfigId is " + ldapUserRegistryId + "\n"
except:
print "AdminConfig.list('LDAPUserRegistry') caught an exception\n"
try:
secMbeans = AdminControl.queryNames('WebSphere:type=SecurityAdmin,*')
if len(secMbeans) == 0:
print "Security Mbean was not found\n"
return
secMbean = secMbeans.split(lineSeparator)[0]
print "Got Security Mbean is " + secMbean + "\n"
except:
print "AdminControl.queryNames('WebSphere:type=SecurityAdmin,*') caught an exception\n"
attrs2 = [["hosts", [[["host", ldapServer], ["port", ldapPort]]]]]
try:
AdminConfig.modify(ldapUserRegistryId, attrs2)
try:
AdminConfig.save()
print "Done setting up attributes values for LDAP User Registry"
print "Updated was saved successfully\n"
except:
print "AdminConfig.save() caught an exception\n"
except:
print "AdminConfig.modify(" + ldapUserRegistryId + ", " + attrs2 + ") caught an exception\n"
return
#-------------------------------------------------------------------------------
# Main entry point
#-------------------------------------------------------------------------------
if len(sys.argv) < 2 or len(sys.argv) > 3:
print("LDAPAdd: this script requires 2 parameters: LDAP server hostname and LDAP server port number\n")
print("e.g.: LDAPAdd ldaphost 389\n")
sys.exit(1)
else:
ldapServer = sys.argv[0]
ldapPort = sys.argv[1]
LDAPAdd(ldapServer, ldapPort)
sys.exit(0)