月度归档:2013年12月

ZooKeeper管理员指南——部署与管理ZooKeeper

本文以ZooKeeper3.4.3版本的官方指南为基础:http://zookeeper.apache.org/doc/r3.4.3/zookeeperAdmin.html,补充一些作者运维实践中的要点,围绕ZK的部署和运维两个方面讲一些管理员需要知道的东西。本文并非一个ZK搭建的快速入门,关于这方面,可以查看《ZooKeeper快速搭建》。

1.部署

本章节主要讲述如何部署ZooKeeper,包括以下三部分的内容:

· 系统环境

· 集群模式的配置

· 单机模式的配置

系统环境和集群模式配置这两节内容大体讲述了如何部署一个能够用于生产环境的ZK集群。如果仅仅是想在单机上将ZK运行起来,进行一些开发与测试,那么第三部分或许是你的菜。

1.1系统环境

1.1.1平台支持

平 台

运行client

运行server

开发环境

生产环境

GNU/Linux

Sun Solaris

FreeBSD

ⅹ,对nio的支持不好

Win32

MacOSX

:运行client是指作为客户端,与server进行数据通信,而运行server是指将ZK作为服务器部署运行。

1.1.2软件环境

ZooKeeper Server是一个Java语言实现的分布式协调服务框架,因此需要6或更高版本的JDK支持。集群的机器数量方面,宽泛的讲,其实是任意台机器都可以部 署运行的,注意,这里并没有说一定要奇数台机器哦!通常情况下,建议使用3台独立的Linux服务器构成的一个ZK集群。

1.2集群模式的配置

为了确保ZooKeeper服务的稳定与可靠性,通常是搭建成一个ZK集群来对外提供服务。关于ZooKeeper,需要明确一个很重要的特性:集 群中只要有过半的机器是正常工作的,那么整个集群对外就是可用的(本文下面就用“过半存活即可用”来代替这个特性吧^-^)。正是基于这个特性,建议是将 ZK集群的机器数量控制为奇数较为合适。为什么选择奇数台机器,我们可以来看一下,假如是4台机器构成的ZK集群,那么只能够允许集群中有一个机器 down掉,因为如果down掉2台,那么只剩下2台机器,显然没有过半。而如果是5台机器的集群,那么就能够对2台机器down掉的情况进行容灾了。

你可以按照以下步骤来配置一个ZK机器,更多详细步骤请查看《ZooKeeper快速搭建》:

1. 安装JDK。相关链接:http://java.sun.com/javase/downloads/index.jsp

2. 设置Java heap 大小。避免内存与磁盘空间的交换,能够大大提升ZK的性能,设置合理的heap大小则能有效避免此类空间交换的触发。在正式发布上线之前,建议是针对使用 场景进行一些压力测试,确保正常运行后内存的使用不会触发此类交换。通常在一个物理内存为4G的机器上,最多设置-Xmx为3G。

3. 下载安装ZooKeeper,相关链接:http://zookeeper.apache.org/releases.html

4. 配置文件zoo.cfg。初次使用zookeeper,按照如下这个简单配置即可:

tickTime=2000
dataDir=/var/lib/zookeeper/
clientPort=2181
initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

本文后续章节会对这些参数进行详细的介绍,这里只是简单说几点:集群中的每台机器都需要感知整个集群是由哪几台机器组成的,在配置文件中,可以按照 这样的格式,每行写一个机器配置:server.id=host:port:port. 关于这个id,我们称之为Server ID,标识host机器在集群中的机器序号,在每个ZK机器上,我们需要在数据目录(数据目录就是dataDir参数指定的那个目录)下创建一个myid 文件,myid中就是这个Server ID数字。

在ZooKeeper的设计中,集群中任意一台机器上的zoo.cfg文件的内容都是一致的。因此最好是用SVN把这个文件管理起来,保证每个机器都能共享到一份相同的配置。

5. 关于myid文件。myid文件中只有一个数字,即一个Server ID。例如,server.1 的myid文件内容就是“1”。注意,请确保每个server的myid文件中id数字不同,并且和server.id=host:port:port中 的id一致。另外,id的范围是1~255。

6. 至此,配置文件基本ok,可以尝试使用如下命令来启动zookeeper了:

$ java -cp zookeeper.jar:lib/slf4j-api-1.6.1.jar:lib/slf4j-log4j12-1.6.1.jar:lib/log4j-1.2.15.jar:conf \ org.apache.zookeeper.server.quorum.QuorumPeerMainzoo.cfg

注意,不同的ZK版本,依赖的log4j和slf4j版本也是不一样的,请看清楚自己的版本后,再执行上面这个 命令。QuorumPeerMain类会启动ZooKeeper Server,同时,JMX MB也会被启动,方便管理员在JMX管理控制台上进行ZK的控制。这里有对ZK JMX的详细介绍:http://zookeeper.apache.org/doc/r3.4.3/zookeeperJMX.html.  另外,完全可以有更简便的方式,直接使用%ZK_HOME%/bin 中的脚本启动即可。

./zkServer.sh start

7. 连接ZK host来检验部署是否成功。
->Java语言的话,可以通过运行这个命令来检测:

$ java -cp zookeeper.jar:lib/slf4j-api-1.6.1.jar:lib/slf4j-log4j12-1.6.1.jar:lib/log4j-1.2.15.jar:conf:src/java/lib/jline-0.9.94.jar \ org.apache.zookeeper.ZooKeeperMain -server 127.0.0.1:2181

->如果是C语言的话,方法如下:

$ make cli_st
$ make cli_mt

然后按照的这样的方式连接ZK:$ cli_mt 127.0.0.1:2181。无论运行哪种客户端,最终都是一个类似于文件系统的命令行操作。

注意:除了上面这种检测方法,其实%ZK_HOME%/bin也有其它脚本,下面这个命令执行后,就进入了zookeeper树状结构的文件系统中。

./zkCli.sh

另外,还有一种方式,能够查看ZK服务器当前状态,如下,这个能够很好的看出目前这个机器的运行情况了:

$ echo stat|nc localhost 2181
Zookeeper version: 3.4.3-1240972, built on 02/06/2012 10:48 GMT
Clients:
/127.0.0.1:40293[0](queued=0,recved=1,sent=0)

Latency min/avg/max: 1/2/3
Received: 4
Sent: 3
Outstanding: 0
Zxid: 0×200000006
Mode: leader
Node count: 4

1.3单机模式的配置

如果你想安装一个ZooKeeper来进行开发测试,通常可以使用单机模式来启动ZK。大体的步骤和上面说的是一样了,除了配置文件会更加简单一 些。详细的配置方法可以查看这里:http://zookeeper.apache.org/doc/r3.4.3 /zookeeperStarted.html#sc_InstallingSingleMode

2.运 维

本章节主要要讲述如何更好地运维ZooKeepr,大致包含以下几部分内容:

· 部署方案的设计

· 日常运维

· Server的自检恢复

· 监控

· 日志管理

· 数据加载出错

· 配置参数详解

· 常用的四字命令

· 数据文件管理

· 注意事项

2.1部署方案的设计

我们常说的ZooKeeper能够提供高可用分布式协调服务,是要基于以下两个条件:

集群中只有少部分的机器不可用。这里说的不可用是指这些机器或者是本身down掉了,或者是因为网络原因,有一部分机器无法和集群中其它绝大部分的机器通信。例如,如果ZK集群是跨机房部署的,那么有可能一些机器所在的机房被隔离了。

正确部署ZK server,有足够的磁盘存储空间以及良好的网络通信环境。

下面将会从集群和单机两个维度来说明,帮助zookeeper管理员尽可能地提高ZK集群的可用性。

2.1.1集群维度

在上面提到的“过半存活即可用”特性中已经讲到过,整个集群如果对外要可用的话,那么集群中必须要有过半的机器是正常工作并且彼此之间能够正常通 信。基于这个特性,那么如果想搭建一个能够允许F台机器down掉的集群,那么就要部署一个由2xF+1 台机器构成的ZK集群。因此,一个由3台机器构成的ZK集群,能够在down掉一台机器后依然正常工作,而5台机器的集群,能够对两台机器down掉的情 况容灾。注意,如果是一个6台机器构成的ZK集群,同样只能够down掉两台机器,因为如果down掉3台,剩下的机器就没有过半了。基于这个原因,ZK集群通常设计部署成奇数台机器。

所以,为了尽可能地提高ZK集群的可用性,应该尽量避免一大批机器同时down掉的风险,换句话说,最好能够为每台机器配置互相独立的硬件环境。举 个例子,如果大部分的机器都挂在同一个交换机上,那么这个交换机一旦出现问题,将会对整个集群的服务造成严重的影响。其它类似的还有诸如:供电线路,散热 系统等。其实在真正的实践过程中,如果条件允许,通常都建议尝试跨机房部署。毕竟多个机房同时发生故障的机率还是挺小的。

2.1.2单机维度

对于ZK来说,如果在运行过程中,需要和其它应用程序来竞争磁盘,CPU,网络或是内存资源的话,那么整体性能将会大打折扣。
首先来看看磁盘对于ZK性能的影响。客户端对ZK的更新操作都是永久的,不可回退的,也就是说,一旦客户端收到一个来自server操作成功的响应,那么 这个变更就永久生效了。为做到这点,ZK会将每次更新操作以事务日志的形式写入磁盘,写入成功后才会给予客户端响应。明白这点之后,你就会明白磁盘的吞吐 性能对于ZK的影响了,磁盘写入速度制约着ZK每个更新操作的响应。为了尽量减少ZK在读写磁盘上的性能损失,不仿试试下面说的几点:

· 使用单独的磁盘作为事务日志的输出(比如我们这里的ZK集群,使用单独的挂载点用于事务日志的输出)。事务日志的写性能确实对ZK性能,尤其是更 新操作的性能影响很大,所以想办法搞到一个单独的磁盘吧!ZK的事务日志输出是一个顺序写文件的过程,本身性能是很高的,所以尽量保证不要和其它随机写的 应用程序共享一块磁盘,尽量避免对磁盘的竞争。

· 尽量避免内存与磁盘空间的交换。如果希望ZK能够提供完全实时的服务的话,那么基本是不允许操作系统触发此类swap的。因此在分配JVM堆大小的时候一定要非常小心,具体在本文最后的“注意事项”章节中有讲到。

2.2日常运维

对zookeeper运维是一个长期积累经验的过程,希望以下几点对广大ZK运维人员有一定的帮助:

· 清理数据目录

上文中提到dataDir目录指定了ZK的数据目录,用于存储ZK的快照文件(snapshot)。另外,默认情况下,ZK的事务日志也会存储在这 个目录中。在完成若干次事务日志之后(在ZK中,凡是对数据有更新的操作,比如创建节点,删除节点或是对节点数据内容进行更新等,都会记录事务日 志),ZK会触发一次快照(snapshot),将当前server上所有节点的状态以快照文件的形式dump到磁盘上去,即snapshot文件。这里 的若干次事务日志是可以配置的,默认是100000,具体参看下文中关于配置参数“snapCount”的介绍。
考虑到ZK运行环境的差异性,以及对于这些历史文件,不同的管理员可能有自己的用途(例如作为数据备份),因此默认ZK是不会自动清理快照和事务日志,需 要交给管理员自己来处理。这里是我们用的清理方法,保留最新的66个文件,将它写到crontab中,每天凌晨2点触发一次:

#!/bin/bash

#snapshot file dir
dataDir=/home/yinshi.nc/test/zk_data/version-2
#tran log dir
dataLogDir=/home/yinshi.nc/test/zk_log/version-2
#zk log dir
logDir=/home/yinshi.nc/test/logs
#Leave 66 files
count=66
count=$[$count+1]
ls -t $dataLogDir/log.* | tail -n +$count | xargs rm -f
ls -t $dataDir/snapshot.* | tail -n +$count | xargs rm -f
ls -t $logDir/zookeeper.log.* | tail -n +$count | xargs rm -f

#find /home/yinshi.nc/taokeeper/zk_data/version-2 -name “snap*” -mtime +1 | xargs rm -f
#find /home/yinshi.nc/taokeeper/zk_logs/version-2 -name “log*” -mtime +1 | xargs rm -f
#find /home/yinshi.nc/taokeeper/logs/ -name “zookeeper.log.*” -mtime +1 | xargs rm –f

其实,仅管ZK没有自动帮我们清理历史文件,但是它的还是提供了一个叫PurgeTxnLog的 工具类,实现了一种简单的历史文件清理策略,可以在这里看一下他的使用方法:http://zookeeper.apache.org/doc/r3.4.3/api/index.html 简单使用如下:

java -cp zookeeper.jar:lib/slf4j-api-1.6.1.jar:lib/slf4j-log4j12-1.6.1.jar:lib/log4j-1.2.15.jar:conf org.apache.zookeeper.server.PurgeTxnLog<dataDir><snapDir> -n <count>

最后一个参数表示希望保留的历史文件个数,注意,count必须是大于3的整数。可以把这句命令写成一个定时任务,以便每天定时执行清理。
注意: 从3.4.0版本开始, zookeeper提供了自己清理历史文件的功能了,相关的配置参数是autopurge.snapRetainCount和 autopurge.purgeInterval,在本文后面会具体说明。更多关于zookeeper的日志清理,可以阅读这个文章《ZooKeeper日志清理》

· ZK程序日志

这里说两点,ZK默认是没有向ROLLINGFILE文件输出程序运行时日志的,需要我们自己在conf/log4j.properties中配置 日志路径。另外,没有特殊要求的话,日志级别设置为INFO或以上,我曾经测试过,日志级别设置为DEBUG的话,性能影响很大!

2.3 Server的自检恢复

ZK运行过程中,如果出现一些无法处理的异常,会直接退出进程,也就是所谓的快速失败(fail fast)模式。在上文中有提到,“过半存活即可用”的特性使得集群中少数机器down掉后,整个集群还是可以对外正常提供服务的。另外,这些down掉 的机器重启之后,能够自动加入到集群中,并且自动和集群中其它机器进行状态同步(主要就是从Leader那里同步最新的数据),从而达到自我恢复的目的。
因此,我们很容易就可以想到,是否可以借助一些工具来自动完成机器的状态检测与重启工作。回答是肯定的,这里推荐两个工具:
Daemontools(http://cr.yp.to/daemontools.html) 和 SMF(http://en.wikipedia.org/wiki/Service_Management_Facility),能够帮助你监控ZK进程,一旦进程退出后,能够自动重启进程,从而使down掉的机器能够重新加入到集群中去~

2.4 监控

有几种方法:

ZK提供一些简单但是功能强大的4字命令,通过对这些4字命令的返回内容进行解析,可以获取不少关于ZK运行时的信息。

用jmx也能够获取一些运行时信息,详细可以查看这里:http://zookeeper.apache.org/doc/r3.4.3/zookeeperJMX.html

淘宝网已经实现的一个ZooKeeper监控——TaoKeeper,已开源,在这里: http://rdc.taobao.com/team/jm/archives/1450,主要功能如下:

· 机器CPU/MEM/LOAD的监控

· ZK日志目录所在磁盘空间监控

· 单机连接数的峰值报警

· 单机Watcher数的峰值报警

· 节点自检

· ZK运行时信息展示

2.5 日志管理

ZK使用log4j作为日志系统,conf目录中有一份默认的log4j配置文件,注意,这个配置文件中还没有开启ROLLINGFILE文件输出,配置下即可。其它关于log4j的详细介绍,可以移步到log4j的官网:http://logging.apache.org/log4j/1.2/manual.html#defaultInit

2.6加载数据出错

ZK在启动的过程中,首先会根据事务日志中的事务日志记录,从本地磁盘加载最后一次提交时候的快照数据,如果读取事务日志出错或是其它问题(通常在 日志中可以看到一些IO异常),将导致server将无法启动。碰到类似于这种数据文件出错导致无法启动服务器的情况,一般按照如下顺序来恢复:

确认集群中其它机器是否正常工作,方法是使用“stat”这个命令来检查:echo stat|nc ip 2181

如果确认其它机器是正常工作的(这里要说明下,所谓正常工作还是指集群中有过半机器可用),那么可以开始删除本机的一些数据了,删除$dataDir/version-2和$dataLogDir/version-2 两个目录下的所有文件。

重启server。重启之后,这个机器就会从Leader那里同步到最新数据,然后重新加入到集群中提供服务。

2.7 配置参数详解(主要是%ZOOKEEPER_HOME%/conf/zoo.cfg文件)

参数名

说明

clientPort

客户端连接server的端口,即对外服务端口,一般设置为2181吧。

dataDir

存储快照文件snapshot的目录。默认情况下,事务日志也会存储在这里。建议同时配置参数dataLogDir, 事务日志的写性能直接影响zk性能。

tickTime

ZK中的一个时间单元。ZK中所有时间都是以这个时间单元为基础,进行整数倍配置的。例如,session的最小超时时间是2*tickTime。

dataLogDir

事务日志输出目录。尽量给事务日志的输出配置单独的磁盘或是挂载点,这将极大的提升ZK性能。
(No Java system property)

globalOutstandingLimit

最大请求堆积数。默认是1000。ZK运行的时候, 尽管server已经没有空闲来处理更多的客户端请求了,但是还是允许客户端将请求提交到服务器上来,以提高吞吐性能。当然,为了防止Server内存溢出,这个请求堆积数还是需要限制下的。
(Java system property:zookeeper.globalOutstandingLimit.)

preAllocSize

预先开辟磁盘空间,用于后续写入事务日志。默认是64M,每个事务日志大小就是64M。如果ZK的快照频率较大的话,建议适当减小这个参数。(Java system property:zookeeper.preAllocSize)

snapCount

每进行snapCount次事务日志输出后,触发一次快照(snapshot), 此时,ZK会生成一个snapshot.*文件,同时创建一个新的事务日志文件log.*。默认是100000.(真正的代码实现中,会进行一定的随机数 处理,以避免所有服务器在同一时间进行快照而影响性能)(Java system property:zookeeper.snapCount)

traceFile

用于记录所有请求的log,一般调试过程中可以使用,但是生产环境不建议使用,会严重影响性能。(Java system property:?requestTraceFile)

maxClientCnxns

单个客户端与单台服务器之间的连接数的限制,是ip级别的,默认是60,如果设置为0,那么表明不作任何限制。请注意这 个限制的使用范围,仅仅是单台客户端机器与单台ZK服务器之间的连接数限制,不是针对指定客户端IP,也不是ZK集群的连接数限制,也不是单台ZK对所有 客户端的连接数限制。指定客户端IP的限制策略,这里有一个patch,可以尝试一下:http://rdc.taobao.com/team/jm/archives/1334(No Java system property)

clientPortAddress

对于多网卡的机器,可以为每个IP指定不同的监听端口。默认情况是所有IP都监听clientPort指定的端口。New in 3.3.0

minSessionTimeoutmaxSessionTimeout

Session超时时间限制,如果客户端设置的超时时间不在这个范围,那么会被强制设置为最大或最小时间。默认的Session超时时间是在2 * tickTime ~ 20 * tickTime这个范围 New in 3.3.0

fsync.warningthresholdms

事务日志输出时,如果调用fsync方法超过指定的超时时间,那么会在日志中输出警告信息。默认是1000ms。(Java system property:fsync.warningthresholdms) New in 3.3.4

autopurge.purgeInterval

在上文中已经提到,3.4.0及之后版本,ZK提供了自动清理事务日志和快照文件的功能,这个参数指定了清理频率,单位是小时,需要配置一个1或更大的整数,默认是0,表示不开启自动清理功能。(No Java system property) New in 3.4.0

autopurge.snapRetainCount

这个参数和上面的参数搭配使用,这个参数指定了需要保留的文件数目。默认是保留3个。(No Java system property) New in 3.4.0

electionAlg

在之前的版本中, 这个参数配置是允许我们选择leader选举算法,但是由于在以后的版本中,只会留下一种“TCP-based version of fast leader election”算法,所以这个参数目前看来没有用了,这里也不详细展开说了。(No Java system property)

initLimit

Follower在启动过程中,会从Leader同步所有最新数据,然后确定自己能够对外服务的起始状态。Leader允许F在initLimit时间内完成这个工作。通常情况下,我们不用太在意这个参数的设置。如果ZK集群的数据量确实很大了,F在启动的时候,从Leader上同步数据的时间也会相应变长,因此在这种情况下,有必要适当调大这个参数了。(No Java system property)

syncLimit

在运行过程中,Leader负责与ZK集群中所有机器进行通信,例如通过一些心跳检测机制,来检测机器的存活状态。如果 L发出心跳包在syncLimit之后,还没有从F那里收到响应,那么就认为这个F已经不在线了。注意:不要把这个参数设置得过大,否则可能会掩盖一些问 题。(No Java system property)

leaderServes

默认情况下,Leader是会接受客户端连接,并提供正常的读写服务。但是,如果你想让Leader专注于集群中机器的协调,那么可以将这个参数设置为no,这样一来,会大大提高写操作的性能。(Java system property: zookeeper.leaderServes)。

server.x=[hostname]:nnnnn[:nnnnn]

这里的x是一个数字,与myid文件中的id是一致的。右边可以配置两个端口,第一个端口用于F和L之间的数据同步和其它通信,第二个端口用于Leader选举过程中投票通信。
(No Java system property)

group.x=nnnnn[:nnnnn]weight.x=nnnnn

对机器分组和权重设置,可以 参见这里(No Java system property)

cnxTimeout

Leader选举过程中,打开一次连接的超时时间,默认是5s。(Java system property: zookeeper.cnxTimeout)

zookeeper.DigestAuthenticationProvider
.superDigest

ZK权限设置相关,具体参见《使用super身份对有权限的节点进行操作》《ZooKeeper权限控制》

skipACL

对所有客户端请求都不作ACL检查。如果之前节点上设置有权限限制,一旦服务器上打开这个开头,那么也将失效。(Java system property:zookeeper.skipACL)

forceSync

这个参数确定了是否需要在事务日志提交的时候调用FileChannel.force来保证数据完全同步到磁盘。(Java system property:zookeeper.forceSync)

jute.maxbuffer

每个节点最大数据量,是默认是1M。这个限制必须在server和client端都进行设置才会生效。(Java system property:jute.maxbuffer)

2.8 常用的四字命令

参数名

说明

conf

输出server的详细配置信息。New in 3.3.0 

$>echo conf|nc localhost 2181
clientPort=2181
dataDir=/home/test/taokeeper/zk_data/version-2
dataLogDir=/test/admin/taokeeper/zk_log/version-2
tickTime=2000
maxClientCnxns=1000
minSessionTimeout=4000
maxSessionTimeout=40000
serverId=2
initLimit=10
syncLimit=5
electionAlg=3
electionPort=3888
quorumPort=2888
peerType=0

cons

输出指定server上所有客户端连接的详细信息,包括客户端IP,会话ID等。
New in 3.3.0类似于这样的信息:

$>echo cons|nc localhost 2181
/1.2.3.4:43527[1](queued=0,recved=152802,sent=152806,sid=0x2389e662b98c424,lop=PING,
est=1350385542196,to=6000,lcxid=0×114,lzxid=0xffffffffffffffff,lresp=1350690663308,
llat=0,minlat=0,avglat=0,maxlat=483)
……

crst

功能性命令。重置所有连接的统计信息。New in 3.3.0

dump

这个命令针对Leader执行,用于输出所有等待队列中的会话和临时节点的信息。

envi

用于输出server的环境变量。包括操作系统环境和Java环境。

ruok

用于测试server是否处于无错状态。如果正常,则返回“imok”,否则没有任何响应。
注意:ruok不是一个特别有用的命令,它不能反映一个server是否处于正常工作。“stat”命令更靠谱。

stat

输出server简要状态和连接的客户端信息。

srvr

和stat类似,New in 3.3.0 

$>echo stat|nc localhost 2181
Zookeeper version: 3.3.5-1301095, built on 03/15/2012 19:48 GMT
Clients:
/10.2.3.4:59179[1](queued=0,recved=44845,sent=44845)

Latency min/avg/max: 0/0/1036
Received: 2274602238
Sent: 2277795620
Outstanding: 0
Zxid: 0xa1b3503dd
Mode: leader
Node count: 37473

$>echo srvr|nc localhost 2181
Zookeeper version: 3.3.5-1301095, built on 03/15/2012 19:48 GMT
Latency min/avg/max: 0/0/980
Received: 2592698547
Sent: 2597713974
Outstanding: 0
Zxid: 0xa1b356b5b
Mode: follower
Node count: 37473

srst

重置server的统计信息。

wchs

列出所有watcher信息概要信息,数量等:New in 3.3.0 

$>echo wchs|nc localhost 2181
3890 connections watching 537 paths
Total watches:6909

wchc

列出所有watcher信息,以watcher的session为归组单元排列,列出该会话订阅了哪些path:New in 3.3.0 

$>echo wchc|nc localhost 2181
0x2389e662b97917f
/mytest/test/path1/node1
0x3389e65c83cd790
/mytest/test/path1/node2
0x1389e65c7ef6313
/mytest/test/path1/node3
/mytest/test/path1/node1

wchp

列出所有watcher信息,以watcher的path为归组单元排列,列出该path被哪些会话订阅着:New in 3.3.0 

$>echo wchp|nc localhost 2181
/mytest/test/path1/node
0x1389e65c7eea4f5
0x1389e65c7ee2f68
/mytest/test/path1/node2
0x2389e662b967c29
/mytest/test/path1/node3
0x3389e65c83dd2e0
0x1389e65c7f0c37c
0x1389e65c7f0c364

注意,wchc和wchp这两个命令执行的输出结果都是针对session的,对于运维人员来说可视化效果并不理想,可以尝试将cons命令执行输出的信息整合起来,就可以用客户端IP来代替会话ID了,具体可以看这个实现:http://rdc.taobao.com/team/jm/archives/1450

mntr

输出一些ZK运行时信息,通过对这些返回结果的解析,可以达到监控的效果。New in 3.4.0 

$ echo mntr | nc localhost 2185
zk_version 3.4.0
zk_avg_latency 0
zk_max_latency 0
zk_min_latency 0
zk_packets_received 70
zk_packets_sent 69
zk_outstanding_requests 0
zk_server_state leader
zk_znode_count 4
zk_watch_count 0
zk_ephemerals_count 0
zk_approximate_data_size 27
zk_followers 4 – only exposed by the Leader
zk_synced_followers 4 – only exposed by the Leader
zk_pending_syncs 0 – only exposed by the Leader
zk_open_file_descriptor_count 23 – only available on Unix platforms
zk_max_file_descriptor_count 1024 – only available on Unix platforms

2.9 数据文件管理

默认情况下,ZK的数据文件和事务日志是保存在同一个目录中,建议是将事务日志存储到单独的磁盘上。

2.9.1数据目录

ZK的数据目录包含两类文件:

· myid – 这个文件只包含一个数字,和server id对应。

· snapshot. – 按zxid先后顺序的生成的数据快照。

集群中的每台ZK server都会有一个用于惟一标识自己的id,有两个地方会使用到这个id:myid文件和zoo.cfg文件中。myid文件存储在dataDir目 录中,指定了当前server的server id。在zoo.cfg文件中,根据server id,配置了每个server的ip和相应端口。Zookeeper启动的时候,读取myid文件中的server id,然后去zoo.cfg 中查找对应的配置。

zookeeper在进行数据快照过程中,会生成 snapshot文件,存储在dataDir目录中。文件后缀是zxid,也就是事务id。(这个zxid代表了zk触发快照那个瞬间,提交的最后一个事 务id)。注意,一个快照文件中的数据内容和提交第zxid个事务时内存中数据近似相同。仅管如此,由于更新操作的幂等性,ZK还是能够从快照文件中恢复 数据。数据恢复过程中,将事务日志和快照文件中的数据对应起来,就能够恢复最后一次更新后的数据了。

2.9.2事务日志目录

dataLogDir目录是ZK的事务日志目录,包含了所有ZK的事务日志。正常运行过程中,针对所有更新操作,在返回客户端“更新成功”的响应 前,ZK会确保已经将本次更新操作的事务日志写到磁盘上,只有这样,整个更新操作才会生效。每触发一次数据快照,就会生成一个新的事务日志。事务日志的文 件名是log.,zxid是写入这个文件的第一个事务id。

2.9.3文件管理

不同的zookeeper server生成的snapshot文件和事务日志文件的格式都是一致的(无论是什么环境,或是什么样的zoo.cfg 配置)。因此,如果某一天生产环境中出现一些古怪的问题,你就可以把这些文件下载到开发环境的zookeeper中加载起来,便于调试发现问题,而不会影 响生产运行。另外,使用这些较旧的snapshot和事务日志,我们还能够方便的让ZK回滚到一个历史状态。

另外,ZK提供的工具类LogFormatter能够帮助可视化ZK的事务日志,帮助我们排查问题,关于事务日志的可以化,请查看这个文章《可视化zookeeper的事务日志》.

需要注意的一点是,zookeeper在运行过程中,不断地生成snapshot文件和事务日志,但是不会自动清理它们,需要管理员来处理。(ZK本身只需要使用最新的snapshot和事务日志即可)关于如何清理文件,上面章节“日常运维”有提到。

2.10 注意事项

2.10.1 保持Server地址列表一致

· 客户端使用的server地址列表必须和集群所有server的地址列表一致。(如果客户端配置了集群机器列表的子集的话,也是没有问题的,只是少了客户端的容灾。)

· 集群中每个server的zoo.cfg中配置机器列表必须一致。

2.10.2 独立的事务日志输出

对于每个更新操作,ZK都会在确保事务日志已经落盘后,才会返回客户端响应。因此事务日志的输出性能在很大程度上影响ZK的整体吞吐性能。强烈建议是给事务日志的输出分配一个单独的磁盘。

2.10.3 配置合理的JVM堆大小

确保设置一个合理的JVM堆大小,如果设置太大,会让内存与磁盘进行交换,这将使ZK的性能大打折扣。例如一个4G内存的机器的,如果你把JVM的 堆大小设置为4G或更大,那么会使频繁发生内存与磁盘空间的交换,通常设置成3G就可以了。当然,为了获得一个最好的堆大小值,在特定的使用场景下进行一 些压力测试。

参考文章:

少儿英语02

02

 

03

 

04

 

05

 

06

 

07

 

08

 

09

 

10

 

11

 

12

 

13

 

14

 

15

 

16

 

17

 

18

 

19

 

20

 

从OpenStack的角度看块存储的世界

作者 王豪迈

块存储,简单来说就是提供了块设备存储的接口。用户需要把块存储卷附加到虚拟机或者裸机上以与其交互。这些卷都是持久的:它们可以从运行实例上被解除或者重新附加而数据保持完整不变。

本文重点介绍块存储服务。我们对目前主流的块存储服务提供商和开源的块存储软件做了一个简要分析,希望能给从事块存储开发的工程师对于块存储一个全局的认识。

下面会先介绍常见的单机块设备工具,以建立对块存储的初步印象。

单机块存储

首先,一个硬盘是一个块设备。内核检测到硬盘后,在/dev/下会看到/dev/sda/。为了用一个硬盘来得到不同的分区来做不同的事,我们使用 fdisk工具得到/dev/sda1、/dev/sda2等。这种方式通过直接写入分区表来规定和切分硬盘,是最死板的分区方式。

1. LVM & Device-mapper

LVM是一种逻辑卷管理器。通过LVM来对硬盘创建逻辑卷组和得到逻辑卷,要比fdisk方式更加弹性。如果你目前对LVM用途还不熟悉或者不大清楚,可参考以下链接:

LVM基于Device-mapper用户程序实现。Device-mapper是一种支持逻辑卷管理的通用设备映射机制,为存储资源管理的块设备驱动提供了一个高度模块化的内核架构。以下链接对Device-mapper架构进行了极好的说明:

2. SAN & iSCSI

在接触了单机下的逻辑卷管理后,你需要了解SAN,目前主流的企业级存储方式。

大部分SAN使用SCSI协议在服务器和存储设备之间传输和沟通,通过在SCSI之上建立不同镜像层,可以实现存储网络的连接。常见的有iSCSIFCPFibre Channel over Ethernet等。

SAN通常需要在专用存储设备中建立,而iSCSI是基于TCP/IP的SCSI映射,通过iSCSI协议和Linux iSCSI项目,我们可以在常见的PC机上建立SAN存储。

对于如何建立在PC机上的SAN,可以参考:

不过,这篇文章提到的iSCSI target管理方式不太方便,通常我们会用targetcli管理target。targetcli可以直接建立和管理不同backstone类型的逻辑卷和不同的export方式,如建立ramdisk并且通过iSCSI export,非常方便。操作方式见targetcli screencast Part 2 of 3: ISCSI – YouTube

以上都是我们经常接触的单机块存储。接下来是本文主要分享的内容:公共云技术服务提供的块存储服务,开源的块存储框架,以及OpenStack目前对块存储的定义和支持情况。

分布式块存储

在面对极具弹性的存储需求和性能要求下,单机或者独立的SAN越来越不能满足企业的需要。如同数据库系统一样,块存储在scale up的瓶颈下也面临着scale out的需要。我们可以用以下几个特点来描述分布式块存储系统的概念:

  1. 分布式块存储可以为任何物理机或者虚拟机提供持久化的块存储设备
  2. 分布式块存储系统管理块设备的创建、删除和attach/detach
  3. 分布式块存储支持强大的快照功能,快照可以用来恢复或者创建新的块设备
  4. 分布式存储系统能够提供不同IO性能要求的块设备

3.1 Amazon EBS

Amazon作为领先的IaaS服务商,其API目前是IaaS的事实标准。Amazon EC2目前在大多数方面远超其他IaaS服务商。Amazon EC2的产品介绍是快速了解Amazon EC2的捷径。

EBS是Amazon提供的块存储服务。通过EBS,用户可以随时增删迁移volume和快照操作。

Amazon EC2实例可以将根设备数据存储在Amazon EBS或者本地实例存储上。使用Amazon EBS时,根设备中的数据将独立于实例的生命周期保留下来,使得在停止实例后仍可以重新启动使用,与笔记本电脑关机并在再次需要时重新启动相似。另一方 面,本地实例存储仅在实例的生命周期内保留。这是启动实例的一种经济方式,因为数据没有存储到根设备中。

Amazon EBS提供两种类型的卷,即标准卷和预配置IOPS卷。它们的性能特点和价格不同,可以根据应用程序的要求和预算定制所需的存储性能。

标准卷可为要求有适度或突发式I/O的应用程序提供存储。这些卷平均可以提供大约100 IOPS,最多可突增至数百IOPS。标准卷也非常适合用作引导卷,其突发能力可提供快速的实例启动时间(通常十几秒)。

预配置IOPS卷旨在为数据库等I/O密集型随机读写工作负载提供可预计的高性能。创建一个卷时,利用预置IOPS为卷确定IOPS速率,随之 Amazon EBS在该卷的生命周期内提供该速率。Amazon EBS目前支持每预配置IOPS卷最多4000 个IOPS。您可以将多个条带式卷组合在一起,为应用程序提供每个Amazon EC2数千IOPS的能力。

EBS可以在卷连接和使用期间实时拍摄快照。不过,快照只能捕获已写入Amazon EBS 卷的数据,不包含应用程序或操作系统已在本地缓存的数据。如果需要确保能为实例连接的卷获得一致的快照,需要先彻底地断开卷连接,再发出快照命令,然后重新连接卷。

EBS快照目前可以跨regions增量备份,意味着EBS快照时间会大大缩短,从另一面增加了EBS使用的安全性。

总的来说,Amazon EBS是目前IaaS服务商最引入注目的服务之一,目前的OpenStack、CloudStack等其他开源框架都无法提供Amazon EBS的弹性和强大的服务。了解和使用Amazon EBS是学习IaaS块存储的最好手段。

3.2 阿里云存储

阿里云是国内的公共云计算服务商。阿里云磁盘目前仅支持在创建云主机的时候绑定云磁盘或者在升级云主机的进行云磁盘扩容,这从根本上就是传统的虚拟主机的特点而不是所谓的“云磁盘”。

从目前的阿里云磁盘的限制:

  1. 无法快速创建或删除volume,在进行扩容时需要升级云主机才能达到,而升级云主机只有在下月云主机套餐到期时才能生效(中国移动套餐的模式)
  2. 一个云主机最多只能绑定3个云磁盘

从阿里云磁盘目前的使用分析,以下是我对阿里云磁盘实现的推测:

  1. 阿里云主机是跟磁盘绑定的,这意味着阿里云的云磁盘是local volume(因此性能还是挺可观的)。用户需要扩容、减少都需要下个月更说明了这点,整个主机在扩容时去调度合适的有足够存储空间的host,然后进行扩容。
  2. 阿里云磁盘是分布式块存储系统,但是由于其QoS无法保证和其他资源调度原因,无法提供足够的块存储支持。

演讲回顾:阿里云存储技术的演进,以及云服务用例最佳实践中了解到阿里云是基于自家的“盘古”系统,那么从实际使用来说,远没达到一般的分布式块存储系统的要求。

4.1 Ceph

Ceph是开源实现的PB级分布式文件系统,其分布式对象存储机制为上层提供了文件接口、块存储接口和对象存储接口。Inktank是Ceph的主要支持商,也是目前Ceph开源社区的主要力量。

Ceph目前是OpenStack的开源块存储实现系统(即Cinder项目的backend driver之一),其实现分为三个部分: OSD,Monitor,MDS。OSD是底层对象存储系统,Monitor是集群管理系统,MDS是用来支持POSIX文件接口的Metadata Server。从Ceph的原始论文《Ceph: Reliable, Scalable, and High-Performance Distributed Storage》来看,Ceph专注于扩展性,高可用性和容错性。Ceph放弃了传统的Metadata查表方式(HDFS)而改用算法(CRUSH)去定位具体的block。

利用Ceph提供的RULES可以弹性地制订存储策略和Pool选择,Monitor作为集群管理系统掌握了全部的Cluster Map,Client在没有Map的情况下需要先向Monitor请求得到,然后通过Object id计算相应的OSD Server。

Ceph的文档可以参考以下链接:

Ceph支持传统的POSIX文件接口,因此需要额外的MDS(Meatadata Server)支持文件元信息(Ceph的块存储和对象存储支持不需要MDS服务)。Ceph将Data和Metadata分离到两个服务上,跟传统的分 布式系统如Lustre相比可以大大增强扩展性。在小文件读写上,Ceph读写文件会有[RTT*2],在每次open时,会先去Metadata Server查询一次,然后再去Object Server。除了Open操作外,Ceph在Delete上也有问题,它需要到Metadata Server擦除对应的Metadata,是n(2)复杂度。Ceph在Metadata上并非只有坏处,通过Metadata Server,像目录列表等目录操作为非常快速,远超GlusterFS等其他分布式文件系统的目录或文件元操作。

如果要用Ceph作为块存储项目,有几个问题需要考虑:

  1. Ceph在读写上不太稳定(有btrfs的原因)。目前Ceph官方推荐XFS作为底层文件系统
  2. Ceph的扩展性较难,如果需要介入Ceph,需要较长时间
  3. Ceph的部署不够简易并且集群不够稳定

4.2 Sheepdog

Sheepdog是另一个分布式块存储系统实现。与Ceph相比,它的最大优势就是代码短小好维护,hack的成本很小。Sheepdog也有很多Ceph不支持的特性,比如说Multi-Disk, Cluster-wide Snapshot等。

Sheepdog主要有两部分,一个是集群管理,另一个是存储服务。集群管理目前使用Corosync或者Zookper来完成,其存储服务的特点是在client和存储host有Cache的实现可以大大减小数据流量。

目前Sheepdog只在QEMU端提供Drive,而缺少library支持,这是Sheepdog目前最主要的问题。但是社区已经有相关的Blueprint在讨论这个问题。

了解Sheepdog的一些相关资料:

目前Taobao是Sheepdog主要用户和社区贡献者。

5. Cinder

OpenStack是目前流 行的IaaS框架,提供了与AWS类似的服务并且兼容其API。OpenStack Nova是计算服务,Swift是对象存储服务,Quantum是网络服务,Glance是镜像服务,Cinder是块存储服务,Keystone是身份 认证服务,Horizon是Dashboard,另外还有Heat、Oslo、Ceilometer、Ironic等等项目。

OpenStack的存储主要分为三大类:

  • 对象存储服务,Swift
  • 块设备存储服务,主要是提供给虚拟机作为“硬盘”的存储。这里又分为两块:
    • 本地块存储
    • 分布式块存储,Cinder
  • 数据库服务,目前是一个正在孵化的项目Trove,前身是Rackspace开源出来的RedDwarf,对应AWS里面的RDC。

Cinder是OpenStack 中提供类似于EBS块存储服务的API框架。它并没有实现对块设备的管理和实际服务,而是为后端不同的存储结构提供了统一的接口,不同的块设备服务厂商在 Cinder中实现其驱动支持以与OpenStack进行整合。后端的存储可以是DAS,NAS,SAN,对象存储或者分布式文件系统。也就是 说,Cinder的块存储数据完整性、可用性保障是由后端存储提供的。在CinderSupportMatrix中可以看到众多存储厂商如NetAPP、IBM、SolidFire、EMC和众多开源块存储系统对Cinder的支持。

从上图我们也可以看到,Cinder只是提供了一层抽象,然后通过其后段支持的driver实现来发出命令来得到回应。关于块存储的分配信息以及选项配置等会被保存到OpenStack统一的DB中。

总结

目前分布式块存储的实现仍然是由Amazon EBS领衔,其卓越稳定的读写性能、强大的增量快照和跨区域块设备迁移,以及令人惊叹的QoS控制都是目前开源或者其他商业实现无法比拟的。

不过Amazon EBS始终不是公司私有存储的一部分,作为企业IT成本的重要部分,块存储正在发生改变。EMC在一个月前发布了其ViPR平台,并开放了其接口,试图接 纳其他厂商和开源实现。Nexenta在颠覆传统的的存储专有硬件,在其上软件实现原来只有专有SDN的能力,让企业客户完全摆脱存储与厂商的绑定。 Inktank极力融合OpenStack并推动Ceph在OpenStack社区的影响力。这些都说明了,无论是目前的存储厂商还是开源社区都在极力推 动整个分布式块存储的发展,存储专有设备的局限性正在进一步弱化了原有企业的存储架构。

在分布式块存储和OpenStack之间,我们可以打造更巩固的纽带,将块存储在企业私有云平台上做更好的集成和运维。

Kerberos原理

来源:http://www.cnblogs.com/jankie/archive/2011/08/22/2149285.html
微软Windows Server 2003操作系统实现Kerberos 版本5的身份认证协议。Windows Server 2003同时也实现了公钥身份认证的扩展。Kerberos身份验证的客户端实现为一个SSPsecurity support provider),能够通过SSPISecurity Support Provider Interface)进行访问。最初的用户身份验证是跟Winlogon的单点登录架构集成在一起的。KerberosKDCKey Distribution Center)跟Windows Server 2003的域控制器DCdomain controller)上的安全服务集成在一起,KDC使用域的活动目录数据库作为它的安全帐户数据库,缺省的Kerberos实现要求活动目录的支持。

这个主题将解释Windows Server 2003是怎样支持Kerberos V5协议及其扩展的。

一 什么是 Kerberos 身份验证

Kerberos V5身份验证协议提供一个在客户端跟服务器端之间或者服务器与服务器之间的身份验证机制(并且是相互的身份验证机制)

Windows Server 2003Kerberos V5身份验证协议实现为一个能够通过SSPSSecurity Support Provider Interface)的SSPsecurity support provider),另外,Windows Server 2003还通过使用智能卡的公共密钥证书(public key certificates)进行初始身份验证来扩展此协议。

Kerberos的密钥分发中心 KDCKey Distribution Center)使用活动目录的服务数据库作为自己安全帐户数据库。NTLM Kerberos的缺省实现都需要活动目录的支持。

Kerberos V5协议假设客户端和服务端的最初信息交换发生在开放的网络环境中,在网上传输的数据包能够被监视并能被任意修改。这个假设的环境,跟现在的因特网非常相似,攻击者可以非常容易的伪装为一个客户端或者一个服务器,也能很容易的窃听和篡改合法客户端和服务端之间的通讯。

微软的Kerberos V5协议实现是:

Windows Server 2003的缺省身份认证

Kerberos V5协议成为Windows 2003的缺省身份验证,Windows Server 2003还为了能支持Windows NT Server 4.0等非Kerberos的操作系统还支持NTLM协议。

基于RFC 1510及其修订草案

Kerberos协议是成熟的、广泛应用的、开放的标准,微软Kerberos V5协议的实现遵循RFC的标准,因此能提供跟其他实现的互操作。

可扩展性

Kerberos 架构允许你指定另外的或者可以替换的安全方案。并且,可以通过智能卡的公钥/私钥来提供缺省的共享安全密钥过程。

1、 Kerberos身份认证带来的好处

Kerberos V5协议比NTLM协议更安全、更灵活,更有效,用Kerberos身份验证能够获得的好处是:

1.1、 身份委派

Windows的服务为某个客户端访问资源时会扮演这个客户端,在多数情况下,在本机上一个服务能够为客户端完成访问资源的工作,因为NTLMKerberos都能为服务提供需要扮演客户端的信息。可是,在分布式应用被设计为前端服务扮演客户端连接到在其他服务器上的后端服务,Kerberos V5协议包括一个允许服务扮演客户端连接到其他服务器上的服务的代理机制,NTLM则没有这样的功能。

Interoperability.

1.2、 互操作

微软的Kerberos V5实现是基于IETF的推荐标准规范。这样,Windows Server 2003Kerberos V5实现就为其他使用Kerberos V5协议的网络的互操作打下了基础。

1.3、 更高效率的身份验证

对于NTLM,为了验证每一个客户端,应用服务器必须连接到域控制器以证实客户端身份。对于Kerberos V5身份验证协议,服务器不用去连接域控制器,相应的,服务器可以检验客户端提供的验证票。客户端可以为特定的服务获取一次验证票并在一次登录过程中反复使用这个验证票。可更新的会话票据(session tickets)替代了pass-through authenticatio(不知道怎么翻译)。

1.4、 相互身份验证

通过使用Kerberos协议,在网络连接的一端都可以验证网络另一端的声明是它自己的实体。虽然NTLM允许服务器验证客户端的身份,但是它没有提供客户端验证服务端身份的功能,也没有提供服务器验证另一个服务器身份的功能。NTLM被设计为假设服务器都是真实的网络环境,Kerberos则没有这个假设。

2、 Kerberos V5协议标准

Kerberos身份验证协议几十年前起源于麻省理工学院,是由“Athena”项目的工程师开发的。第一个公开发行的版本是Kerberos版本4。在被广泛的使用后,协议的开发者发布了Kerberos第五版本。

Kerberos V5现在成为IETF的标准,Windows Server 2003Kerberos V5的实现严格的遵循了RFC 1510定义的标准,另外,Kerberos消息中的安全令牌(security tokens)的格式和机制遵循RFC 1964定义的标准。

Kerberos V5协议规定了以下机制:

l 验证用户身份。当一个用户需要获取访问一个服务器的权利,服务器需要验证用户的身份,考虑一个场景,用户声称他是,比如,Alice@tailspintoys.com。因为访问资源是基于身份关联的许可,服务器必须确定用户就是他自己声称的用户。

l 安全的打包用户名,用户名(用户的主名,在本例中就是Alice@tailspintoys.com),和用户的身份信任凭证(credentials)被打包在一个叫做票据(ticket)的数据结构中

l 安全的传送用户信任凭证。票据被加密后,Kerberos消息在网络上传送用户的信任凭证(credentials)。

注意:

虽然Kerberos协议验证用户的身份,它并不授权访问。这是个重要的区别。在其他情形中的票据,象驾驶执照,就同时提供了身份和驾驶车辆的许可。Kerberos的票据仅仅用来证明这个用户就是它自己声称的那个用户。在用户身份得以确认后,本地的安全权限将决定给予访问权限或者拒绝访问。

2.1、 密钥

Kerberos消息被多种加密密钥加密以确保没人能够篡改客户的票据或者Kerberos消息中的其他数据。

l 长期密钥(Long-term key

一个密钥(只有目标服务器和KDC知道),并用来加密客户端访问这个目标服务器票据的密钥。

l Client/server会话密钥(session key

一个短期的、单此会话的密钥,是在用户的身份和权限已经被确认后由KDC建立的用于这个用户的跟某个服务器之间的加密往来信息使用的密钥

l KDC/用户 会话密钥(session key.

KDC跟用户共享的一个密钥,被用于加密这个用户跟KDC之间的消息。

 

Kerberos V5协议使用了对称加密和非对称加密两种加密技术

因为大多数Kerberos的加密方式是基于只用于KDC和用户之间或者KDC和网络服务之间的密钥,Kerberos V5被设计为采用对称加密,即使用同一个密钥来加密和加密消息。

微软的Kerberos协议实现能够使用有限的非对称加密,一个私钥/公钥对被用于加密和解密来自客户端或者网络服务的初始验证信息。

2.2、 Kerberos 身份验证防止数据包重用

Kerberos身份验证机制建立并安全的传送一个带有客户票据的信任凭证(通常基于一个唯一的时间戳),信任凭证是唯一并且一次使用有效。这个限制使有人获取并重用客户端票据或者尝试偷取客户的身份的可能性降到最小。

3、 Kerberos V5协议的扩展

Windows Server 2003实现Kerberos V5协议的扩展,这个扩展在初始身份认证时采用公钥证书来替代常规的对称加密密钥。这个改进允许协议支持用智能卡交互登录。公钥身份验证扩展是基于IETF工作组的草案协议。

4、 Kerberos身份验证的相关技术

下图显示了Windows Server 2003Kerberos身份验证同其它技术如何配合的。依赖是客户端或服务端应用是用户模式(user-mode)还是核心模式(kernel-mode)的应用,他们分别使用Secur32.dll 或者Ksecdd.sys,调用SSPILocal Security Authority Subsystem (LSASS)通讯

kerberos-GetOpenContent-01

下表是参与kerberos身份验证的组件的描述

Component

Description

Kerberos.dll

被用来口令或者智能卡交互式登录实现工业标准的协议SSP。它也是Windows 2000 Windows Server 2003首选的身份验证方式。

Kdcsvc.dll

Kerberos密钥分发中心(KDC)服务,它回应客户端票据授权票(ticket-granting tickets)的申请

Ksecdd.sys

在核心模式(kernel-mode)下用户跟LSASS通讯的核心安全设备驱动

Lsasrv.dll

LSA服务,强制安全策略和担当LSA安全包管理器

Secur32.dll

Secur32.dll 是在用户模式(user mode)下实现SSPI的组件

Windows Server 2003是用SSP来实现Kerberos V5身份验证协议,是操作系统提供的一个动态链接库(DLL),系统使用Kerberos SSP, Kerberos.dll,是身份验证的第一选择。在LSA为一个交互式登录的用户建立了一个安全的上下文,为了支持Kerberos信息的签名和封装,正在运行的用户安全上下文装载另外一个Kerberos SSP实例

因为Kerberos身份验证协议是Windows Server 2003首选协议,所有域服务都支持Kerberos SSP,包括:

l AD活动目录要求使用LDAPLightweight Directory Access Protocol

l 使用RPC的远程服务或workstation management

l 客户-服务器身份验证

l 使用Common Internet File System/server message block (CIFS/SMB)的远程文件访问

l 分布式文件系统管理

l IISintranet身份验证

l Internet Protocol security (IPSec)的安全验证

l 为域用户和计算机发放证书的请求

 

5、 Kerberos 身份验证依赖于

本节讨论和该书Kerberos身份验证依赖项以及和他们的关系

 

5.1、 操作系统

Kerberos 身份认证依赖于客户端功能,这些功能内建于Windows Server 2003Windows XPWindows 2000操作系统。如果一个客户端、域控制器或者目标服务器运行于更早的操作系统下,那它就不天然的支持Kerberos 身份验证。

5.2、 TCP/IP网络连通性

一旦Kerberos 身份认证发生,在客户端、域控制器和目标服务器之间必须有TCP/IP网络连接,关于TCP/IP更多的信息,参考“TCP/IP Technical Reference.

5.3、 域名系统

客户端使用全限定名fully qualified domain nameFQDN)访问域控制器,DNS必须能够保证客户端能够获得这个域控制器的地址。最好不要使用DNS主机文件,关于DNS的更多信息,参看“DNS Technical Reference.

5.4、 域活动目录

Kerberos 身份验证不支持更糟的操作系统,比如Windows NT 4.0。你必须使用活动目录服务中的用户和计算机,本地帐户和Windows NT域帐户不能被由于Kerberos 身份验证

5.5、 时间服务

为了Kerberos 身份验证能正常的发挥作用,在网络中的所有域和森林使用相同的时间源以保证网络中的所有计算机时间同步。一个活动目录域控制器担当权威的时间源,它保证所有的域具有相同的时间。更多信息,参看“Windows Time Service Technical Reference.

5.6、 服务主体名

服务主体名(SPNs) 是运行在服务器上服务的唯一标识符。每一个使用Kerberos 身份验证的服务都需要有个SPN以使客户端能够在网络上标识这个服务。没有正确的设置SPNs, Kerberos 身份验证就是不可能的

二、 Kerberos V5身份验证协议如何工作

Kerberos V5身份验证协议(RFC 1510定义),提供一个在开放的、潜在不安全的网络环境中验证主体身份的方法。这一节讨论RFC标准的Kerberos V5Windows Server 2003如何使用

这节分为以下四个子章节:

l Kerberos SSP结构:说明Windows Server 2003SSPI怎样提供一个访问SSP的机制。

l Kerberos 物理结构:讨论Windows Server 2003中实现Kerberos 身份验证的组件。这些组件包括密钥、票据和密钥分发中心(KDC

l Kerberos V5身份验证协议过程和相互作用:说明Kerberos 身份验证在不同的情形下怎样被使用,Kerberos 消息的细节,并讨论其他相关技术。例子将给出完整的过程,包括没有被Kerberos 身份验证协议定义的相关的组件和过程。一些过程(比如怎样发现一个验证服务,什么信任证书会被通过,信任证书被存放在哪)在Windows系统是特殊的,可能与其他的Kerberos 协议的实现有所不同。

l Kerberos V5协议使用的网络端口:以表格形式展现在Kerberos 身份验证期间使用到的端口。

 

1、 Kerberos SSP架构

Windows Server 2003 Security Support Provider (SSP)来实现Kerberos V5身份验证协议,一个操作系统的动态链接库(DLL)。Windows Server 2003另外还包括针对NTLMSSP。缺省的启动时Windows Server 2003Local Security Authority (LSA) 把两个SSP都装载进来,系统能够两个SSP中的任意一个来验证网络登录和客户端/服务器的连接。使用哪一个SSP取决于连接另一端的机器的能力和个别应用的参数选择。

Microsoft SSPIWindows Server 2003中身份验证的基础,就是说,要求身份验证的应用和底层服务都使用SSPI接口。

SSPIGeneric Security Service API (GSSAPI)Windows Server 2003中的实现,关于GSSAPI的更多信息,请参考RFC 2743 RFC 2744

Windows Server 2003中默认的SSPsNegotiate (SPNEGO), Kerberos, NTLM, Schannel, 和摘要身份验证(Digest authentication protocols))以DLL的形式插入到SSPI,其它的SSP如果能够同SSPI交互也能被插进来。

SSPI 架构图示:

kerberos-GetOpenContent-02

Windows Server 2003中的SSPI提供一个在客户端和服务端已存在的连接上传送身份验证令牌的机制。当两个实体为了能相互安全的通讯需要身份验证时,身份验证的请求被路由到SSPISSPI不管当前正在使用什么网络协议完成身份验证过程,并返回一个透明的(transparent)两进制大对象给连接的另一边的应用。SSPI允许一个应用在一个机器上或网络上使用多种安全模型而不用改变安全系统的接口。

下表是被插入到SSPI的组件的描述。表中的Windows Server 2003中的每个协议都以不同方法来提升不安全网络环境中的通信的安全性。

SSP 层组件:

组件

描述

Kerberos V5 身份验证

一个用口令或者智能卡交互登录的工业标准。它也是Windows 2000 and Windows Server 2003首选身份验证的方式。

NTLM 身份验证

一个质询回应(challenge-response)协议使用来提供比Windows 2000更早的系统的兼容性
摘要身份验证用于Windows Server 2003 LDAPweb身份认证的工业标准,摘要身份的信任凭证被MD5散列后在网上传输。
Schannel一个实现安全套接层(SSL)和传输层安全(TLS)因特网标准身份验证协议的SSPSchannel被用于基于web的服务器身份验证,象当一个用户试图访问一个安全的web服务器。
Negotiate被用于协商使用哪个特定协议的SSP。当一个应用通过SSPI登录到网络,它能够指定一个SSP处理这个登录请求,当应用指定NegotiateNegotiate分析这个请求并选取对客户端配置的安全策略来说最好的SSP处理这个请求

 

2、 Kerberos 物理结构

Kerberos在开放的网络(在网络上传输的数据包可以被随意的监听和修改)上提供客户端和服务端双向的身份验证的机制。为了提供安全的身份验证,Kerberos身份验证使用对称密钥、加密的对象和Kerberos服务。

Kerberos 组件

kerberos-GetOpenContent-03

2.1、 身份验证中使用的密钥

2.1.1 为什么需要密钥?

Kerberos协议严重的依赖于一个验证技术共享密钥。基本的共享密钥的概念十分简单:如果一个秘密只有两个人知道,任何一个人都可以通过他们之间共享的秘密来确定对方的身份。

比如,假设Alice经常给Bob传送信息,Bob在使用这个信息前需要确定这个信息真的就是Alice传送过来的。他们决定通过在他们选择一个只有他们两个人知道一个秘密来解决这个问题,如果一个信息声称来自Alice的,并能以某种方式出示发送者知道的密码,那Bob就能确信发送者就是Alice

剩下的问题就是AliceBob需要解决Alice怎么出示她知道的密码。她可以把密码包含在她发送的信息里面,多半是在最后的签名 - Alice, Our$ecret。 这是简单而有效率的如果他们能确信没有人能够看到他们之间的传送的信息。不幸的是,他们的信息通过的网络上有个用户Carol,他用网络分析工具扫描网络通讯希望有一天能够发现这个密码。因此,Alice不能在她发送的信息里提供密码。为了保持密码的保密性,她必须要能出示这个密码但又不能暴露它。

Kerberos协议用密钥来解决这个问题。替代共享的密码,通讯的双方共享一个密钥,他们使用这个密钥的知识验证另一方的身份。为了使这个技术正常工作,他们共享的密钥必须是对称的,就是说,一个密钥既能够用来加密,又能够用于解密。密钥的一部分知识用来加密,另一部分知识用来解密。

Kerberos身份验证依赖于几个不同类型密钥,密钥的类型有长期对称密钥,长期非对称密钥和短期对称密钥。身份验证协议被设计为使用对称加密,意味着发送端和接收端使用共享的密钥加密和解密。

2.1.2 长期对称密钥:User, System, Service, Inter-realm Keys

长期对称密钥源于一个密码。明码文本的密码通过加密功能被转换为一个密钥(所有的Kerberos V5的实现必须支持DES-CBC-MD5),这里使用DES-CBC-MD5加密的方式把明码文本的密码转换一个密钥。

User keys

当建立一个用户时,用户口令将被用来建立一个user key。在活动目录域,user key和用户对象一起存放在活动目录里,在工作站,用户对象在用户登录时被建立。

System keys

当一个工作站或服务器加入到域,它会收到一个密码,跟用户帐户相似,这个密码用来建立一个system key

Service keys

服务用的密钥基于登录到服务的帐户的密码

所有在同一领域的KDC使用同一个服务密钥。这个密钥基于跟krbtgt帐户关联的口令,每个活动目录月都有这个内建的帐户。

Inter-realm keys

为了跨领域的身份验证的需要,KDC必须共享一个inter-realm key,因为他们共享一个inter-realm key所以领域能够彼此信任,有父子关系的活动目录域共享一个inter-realm key。这个inter-realm key基于Windows 2000 Windows Server 2003的信任传递。如果一个shortcut trust关系被建立,两个域将会交换这个密钥

Kerberos SSP 加密密钥长度

Kerberos SSP支持不同的加密类型,密钥的长度也各不相同。虽然密钥的长度决定着这种加密方法保护程度,密钥的长度不意味着票据的强度。下表列出Kerberos SSP支持的不通加密方法的密钥长度。

不通加密类型的密钥长度

加密算法密钥长度
RC4-HMAC128
DES-CBC-CRC56
DES-CBC-MD556

 

l 关于明文密码通过DES-CBC-MD5产生密钥:

Kerberos 定义了一种对用户密码进行处理以生成一个密钥的算法。在获得 TGT 的过程中 Kerberos 客户机将用这个密钥进行解密,这就是DES-CBC-MD5CBC(密码分组链接 cipher block chaining)模式下的 DES(数据加密标准)。DES 是一个 FIPS(联邦信息处理标准 Federal Information Processing Standards)发表,它描述了一种将要加密的数据(纯文本)和密钥作为输入传递给加密过程的加密算法。根据 DES 算法对密钥和纯文本统一处理以生成一个加密的(密文)形式的纯文本数据。

CBC 是一种加密操作模式,其中纯文本数据分为同样大小的数据块。例如,在 64 DES-CBC 加密中,数据会分为 8 字节的块。如果纯文本数据中的字节数不是您希望每一个块所具有的字节数的整数倍,就要在最后一块中加上适当的数量的字节以使它的大小与其他的块相同。

然后创建一个与您的块具有同样大小的字节数组。这个字节数组称为 初始矢量 (IV)Kerveros 规范定义了所有基于 Kerberos 的应用程序的初始矢量(类似地,其他使用 DES-CBC 的规范定义了它们使用的 IV 值)。之后,取这个 IV、纯文数据的第一块以及密钥并根据 DES 算法对它们共同进行处理,以构成对应于纯文本数据第一个数据块的密文。然后取第一个数据块的密文形式作为第二个块的初始矢量并进行同样的 DES 加密过程以生成第二个纯文本数据块的密文形式。以这种方式继续一块接一块地生成每一个块的密文形式。最后,串接所有密文块以得到全部纯文本数据的密文形式。

下面讨论用户密码经过DES-CBC-MD5处理生成密钥的过程

将用户密码、KDC 域名和用户的用户名串接到一起以构成一个字符串。Kerberos 利用这个串接的字符串而不仅仅是密码生成密钥。为什么要在密钥生成中加入域名和用户名呢?许多用户会在不同的服务器上使用同样的密码。如果我只使用密码生成密钥,那么一个给定的密码在所有 Kerberos 服务器上总是会生成同样的密钥。因而,如果一个黑客可以取得用户在一台 Kerberos 服务器上的密钥,那么,他就可以在所有 Kerberos 服务器上使用同一个密钥。另一方面,如果加入了域名和用户名,那么一个受到这种攻击的密钥将只会侵害特定的域。

得到第 1 步中串接的字符串的字节数组表达。

统计第 2 步中字节数组中的字节数。在这个字节串的后面附加适当数量的零字节以使它成为 8 的整数倍。例如,如果这个字节数组包含 53 个字节,那么就在这个字节数组的最后附加三个字节使它具有 56 个字节。

将第 3 步中附加了字节后的字节数组分为大小相同的块,每一块有 8 个字节。

每隔一个块倒转块的位顺序。换句话说,第一块保持不变,第二块的位顺序应该倒转,第三块应保持不变,第中块的位顺序应倒转,以此类推。

取第一个(未改变的)块并与第二个(倒转的)块进行每一位的 exclusive OR。然后将第一次 exclusive OR 操作得到的结果与第三个(未改变的)块进行另一次 exclusive OR 操作。继续 exclusive OR 操作直到完成了所有块。所有 exclusive OR 操作的最后结果是一个 8 字节长的块。

修正在第 6 步中得到的 8 字节块的奇偶性。每一块的最低有效位保留为奇偶位。统计 8 字节块中每字节中的 1 的个数,如果 1 的个数为偶数,那么就设置最低位为 1 使它成为奇数。例如,如果一个字节的值为 00000000,那么就要将它改为 00000001。如果一个字节中 1 的个数已经为奇数,那么就将它的最低位设置为零。例如,如果一个字节为 00000010,那么就不需要为修正其奇偶性做任何改变。

DES 定义了一些弱的、因而不适合用于加密的密钥。我们的密钥生成过程的第八步是要检查奇偶修正后的字节数组是否是一个弱的密钥。如果是的话,就要用 0xf011110000)与奇偶修正过的 8 字节块进行 exclusive OR。如果奇偶修正得到的不是弱密钥,那么就不需要进行这种 exclusive OR 操作。经过这种弱密钥处理的字节数组是一个临时密钥。

现在我要使用这个临时密钥以 DES-CBC 算法加密第 3 步中得到的附加后的字节数组。这个临时密钥同时作为密钥的值和 DES-CBC 加密的初始矢量的值。回想在前面的讨论中说过,CBC 要求密文块链接。第 9 步的结果是最后 8 字节块的加密结果(放弃所以以前的密文块)。因此,这一步的结果是另一个 8 字节块。

现在我修正第 9 步产生的 8 字节块中的每一个字节的奇偶性。在上面第 7 步中我解释了奇偶性修正。

现在再次检查第 10 步得到的经过奇偶修正的 8 字节块是不是弱密钥(就像在第 8 步中所做的那样)。

基于 SAML 的 WebSphere Application Server 单点登录的场景设计

来源:http://www.ibm.com/developerworks/cn/websphere/library/techarticles/1012_zhangt_saml/1012_zhangt_saml.html

本文向您介绍了如何在 WebSphere 环境下使用 SAML 实现单点登录的场景设计。在向您介绍了 SAML 的基本概念之后,本文将一步步向您介绍如何搭建 WebSphere Application Server 之间的 SAML 单点登录环境。

引言

随着互联网规模的不断扩大,把一个用户的所有信息全部收集到一个地方,既不可能也不需要。不同个人 和组织在与不同的对象打交道时会使用不同类型的信息,例如用户在线购物并付款、会计师保存财政和税款记录等等。经常性地将此信息移动到一个地点,只能使保 持数据的准确性和及时更新更加困难。同时,移动信息还会增加数据在传输中丢失和被窃的可能性。

单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

SAML 介绍

通 常来说,一个企业在物理或逻辑的范围已经界定了企业的 IT 安全。然而,由于在线合作需要共享更可靠的安全服务环境,因此 IT 安全越来越成为人们关注的重点问题。为了解决单点登录的问题,越来越多的系统通过 Web 服务、门户和集成化应用程序彼此链接,对于保证欲共享的信息安全交换的标准的需求也随之日益显著起来。

SAML(安全性断言标记语 言,Security Assertion Markup Language)正是为解决网络安全性问题而发挥其作用。它允许不同安全系统产生的信息进行交换。提供一个健壮且可扩展的数据格式集,在各种环境下交换 数据和身份识别信息。也就是说可使用独立、受管理的多个信息来源中的信息,从而实现身份严整这样的安全服务。

SAML 是一种基于 XML 语言用于传输认证及授权信息的框架,以与主体相关的断言形式表达。在这里,主体是一个实体 ( 人或计算机 ),这个实体在某个安全域中拥有一个特定身份,断言可传递主体执行的认证信息、属性信息及关于是否允许主体访问其资源的授权决定。SAML 在标准行业传输协议环境里工作,例如 HTTP、SMTP 和 FTP; 同时也服务于各种各样的 XML 文件交换框架,例如 SOAP 和 BizTalk。SAML 具备的一个最突出的好处,是使用户能够通过互联网进行安全证书移动。也就是说,使用 SAML 标准作为安全认证和共享资料的中间语言,能够在多个站点之间实现单点登录。

基于 SMAL 的单点登录的场景设计

我 们希望利用 SAML 实现不同服务器之间的单点登录实现。我们设计一种自定义的单点登录场景。这种场景使用 SAML 令牌 API 以及 WebSphere Application Server 所提供的支持 SAML 的 API 开发。下图展示了客户端通过一个与公司服务器存在信任关系的身份验证提供方 (Identity Provider)鉴别并签发 SAML 令牌后,客户端携带被认证的 SAML 令牌继续访问公司服务器,公司服务器将判断此 SAML 令牌中的用户信息是否存在。如果存在,公司服务器直接同意客户端的访问,而不需要要求用户再次进行身份验证了。

图 1. 自定义设计场景

图 1. 自定义设计场景接 下来,客户端可以通过浏览器利用 HTTP 协议将 SAML 令牌传给应用服务器。服务器端通过建立一个信任联合拦截器 (Trust Association Interceptor:TAI )拦截客户端请求。将 HTTP 请求中的 SAML 令牌信息解析并转换成 Subject,同时得到客户端的用户 ID。如果服务器端验证用户 ID 是合法的,则将为客户端提供服务。具体的流程如下:

图 2. 自定义设计场景的流程图

图 2. 自定义设计场景的流程图整个流程如下:

  1. 用户首先请求 WebSphere Application Server 1 的服务。
  2. 服务器 1 的 TAI 判断用户未授权,而将用户的请求转发到一个自定义的登录页面。
  3. 用户在登录页面上输入自己的认证信息,提交后转到第三方 STS 上做认证。
  4. STS 从外部 Registry 判断用户认证信息是否正确。
  5. 如果用户信息正确,STS 会为用户生成一个 SAML 令牌给 SAML 代理。
  6. SAML 代理是一个 Servlet,它会带着这个 SAML 令牌重新请求服务器 1 的服务。
  7. 服务器 1 的 TAI 从 SAML 令牌中提取出 UserID。
  8. TAI 从 Registry 中验证此 UserID 是否合法。
  9. 如果合法,服务器 1 会在 Cookie 为用户生成一个 LTPA 令牌。
  10. 用户的 Cookie 中存在已认证过的 LTPA 令牌,服务器 1 为用户提供服务。
  11. 生成 LTPA 令牌的同时,在同一个安全域之内的服务器将相互共享 LTPA 令牌。
  12. 当用户继续访问 WebSphere Application Server 2 的时候,可以不用认证直接访问服务。

从而实现两个服务器之间通过 SAML 令牌进行单点登录。

基于 SMAL 的单点登录的场景实现

1,实现客户端直接访问服务器上的应用

图 3. 客户端直接访问服务器设计场景

图 3. 客户端直接访问服务器设计场景在 这里我们使用的 WebSphere Application Server 的版本为 7.0.0.7。因为此版本提供了对 SAML 的支持。测试使用的应用服务为 DefaultApplication 中的 snoop 应用。我们先在 WebSphere Application Server 的管理控制端启动全局安全性中的应用程序安全性,使客户端必须认证才可访问 WebSphere Application Server 上的 snoop 应用。

在 WebSphere Application Server 的控制台,进入 Security > Global security 页面,开启应用安全 (Enable application security)

图 4. 开启应用安全

图 4. 开启应用安全重新启动应用服务器之后,访问 snoop 应用(如 http://localhost:9080/snoop),应用提示需要输入验证信息才能访问:

图 5. 访问 snoop 应用提示验证

图 5. 访问 snoop 应用提示验证编写一个简单的 Servlet,设置认证信息并访问 snoop 应用,测试认证通过后是否可以直接访问 Web 应用:

清单 1. snoop 访问代码
   URL url = new URL("http://localhost:9080/snoop"); 
	 HttpURLConnection urlConnection = 
		 (HttpURLConnection) url.openConnection(); 
	 urlConnection.setRequestMethod("GET"); 
	 String encodedUserPass; 
	 String userpass = "username:password"; 
	 encodedUserPass = 
		 new sun.misc.BASE64Encoder().encode (userpass.getBytes()); 
	 urlConnection.setRequestProperty("Authorization", 
		"Basic " + encodedUserPass);

由于之前服务器端设置过安全性,在程序访问此 url 的时候,服务器会判断客户端是否有权限访问。如果设置的认证合法则程序顺利执行,如果认证不合法或者为空则报告没有权限访问的错误。

图 6. 未输入验证信息,页面无权限访问

图 6. 未输入验证信息,页面无权限访问2,实现客户端自签发 SAML 令牌,并通过 TAI 访问服务器上的应用

图 7. 客户端利用 SAML 通过 TAI 访问服务器设计场景

图 7. 客户端利用 SAML 通过 TAI 访问服务器设计场景此 场景比上一场景增加了一个 SAML TAI,即信任联合拦截器 (Trust Association Interceptor:TAI )。TAI 的功能是拦截 HTTP 的请求,执行相应的操作。WebSphere Application Server 自带两种拦截器 com.ibm.ws.security.spnego.TrustAssociationInterceptorImpl 和 com.ibm.ws.security.web.TAMTrustAssociationInterceptorPlus。这里的 TAI 是我们自定义的,用于拦截请求解析 SAML 令牌使用。

自定义的 TAI 需要实现 com.ibm.wsspi.security.tai.TrustAssociationInterceptor 接口。这个接口有三个方法,即:

  • public int initialize(Properties props)

当 TAI 初始化成功,返回 0,TAI 会继续执行 isTargetIntercept 方法。

  • public boolean isTargetInterceptor(HttpServletRequest req)

判断拦截的请求是否为目标请求,如果是返回 true,TAI 会继续执行 negotiateValidateandEstablishTrust 方法。

  • public TAIResult negotiateValidateandEstablishTrust

(HttpServletRequest req, HttpServletResponse res)

TAI 会在此方法中执行所需要的操作。返回的 TAIResult 将通过 WebSphere 服务器自身的安全机制,验证生成的 Subject 及用户 ID 是否合法。

清单 2. isTargetInterceptor 函数代码
 public boolean isTargetInterceptor(HttpServletRequest req) 
			 throws WebTrustAssociationException { 
 String uri = req.getRequestURI() ; 
	 if (uri.indexOf("snoop") != -1) { 			
		 String token = req.getHeader("SAMLToken") ; 
		 if (token != null) { 
			 return true ; 
		 } 
	 } else { 
		 System.out.println("This is not the snoop application."); 
		 return false ; 
	 } 
	 return false ; 
	 // return true if this is the target interceptor, else return false. 
 }

在清单 2 中:

在第 4 行上 isTargetInterceptor 函数首先判断此次请求是否访问的是 snoop 应用,如果是 snoop 应用,则继续执行清单 3 中的 negotiateValidateandEstablishTrust 函数。

清单 3. negotiateValidateandEstablishTrust 函数代码
public TAIResult negotiateValidateandEstablishTrust(HttpServletRequest req, 
	HttpServletResponse res) throws WebTrustAssociationFailedException { 
// validate the request and establish trust. 
  // create and return the TAIResult 
  TAIResult result = null; 
  try { 
   String token = req.getHeader("SAMLToken") ; 
   if(token!=null&&!token.equals("")) { 
   String decodedSAMLToken = Base64Coder.base64Decode(token); 
   SAMLTokenFactory samlFactory = 
       SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV20Token11); 
   ByteArrayInputStream in =
     new ByteArrayInputStream(decodedSAMLToken.getBytes()); 
   SAMLToken samlToken = samlFactory.newSAMLToken(null, in); 
   Subject subject = samlFactory.newSubject(samlToken); 
   result = 
   TAIResult.create(HttpServletResponse.SC_OK, samlToken.getKeyIdentifier(), subject); 
	 } 
	 else { 
	 try { 
      System.out.println("You don't have SAMLToken, 
	  you will be redirected to: http://localhost:9080/SAMLServlet/login.jsp"); 
	 res.sendRedirect("http:// localhost:9080/SAMLServlet/login.jsp"); 
      } catch (IOException e) { 
	   e.printStackTrace(); 
	} 
  } 
 }catch (WSSException e) { 
	 e.printStackTrace(); 
 } 
	 return result ; 
 }

在清单 3 中:

在第 7 行上首先先获得请求头文件 SAMLToken 中的内容。

如果 SAMLToken 中的内容为空,将直接跳转到第 20 行的 login.jsp 页面进行用户登录。

如果 SAMLToken 中的内容不为空,则将其内容解析成 SAMLToken 对象,并从对象中获得并验证用户信息。

如果用户信息正确,TAI 会允许此次 snoop 请求,用户可直接访问 snoop 应用。

编 写完成 TAI 之后,需要将 TAI 类拷贝到 app_server_root/lib/ext directory 路径下并在 WebSphere Application Server 的控制台声明此 TAI。进入 Global security > Trust association > Interceptors,新建一个 SamlTAIImpl,设置相关配置后重启服务器,此 TAI 即可生效。

图 8. 新建 TAI

图 8. 新建 TAI3,通过 SAML 实现两台 WAS 之间进行单点登录

设置好应用安全和 TAI 之后,我们就可以利用 SAML 实现两台 WebSphere Application Server 之间的单点登录了。

图 9. 两 WebSphere Application Server 之间实现单点登录

图 9. 两 WebSphere Application Server 之间实现单点登录s 当用户持 SAML 令牌访问 WebSphere 服务器 1 的时候,服务器 1 的 TAI 将解析出 SAML 令牌中的用户 ID,通过 Registry 判断用户 ID 是否合法。如果合法,服务器 1 将返回给客户端 Cookie 一个 LTPA 令牌。因为可以在 WebSphere Application Server 中设置安全域,在相同安全域中的服务器将共享 LTPA 令牌从而实现单点登录。所以我们就可以带着刚才返回给客户端的 LTPA 令牌直接访问 WebSphere 服务器 2 的服务,而不需要在进行身份验证了。

4,实现客户端通过 STS 签发 SAML 令牌,并通过 TAI 访问服务器上的应用

经 过上述 3 中场景的设计,我们已经能通过程序生成 SAML 令牌,从而实现两个应用服务器见的单点登录。如果我们将程序生成 SAML 令牌转换为利用第三方安全标记服务(STS:Security Token Service)自动生成 SAML 令牌。我们将完成整个 SAML 自定义单点登录的场景设计。

图 10. 客户端通过 STS 利用 SAML 通过 TAI 访问服务器设计场景

图 10. 客户端通过 STS 利用 SAML 通过 TAI 访问服务器设计场景

结束语

随 着互联网规模的不断扩大,单点登录已成为目前比较流行的企业业务整合的解决方案之一。SAML 提供了一个健壮且可扩展的数据格式集,能够实现异构系统下的单点登录和复杂环境间的认证和授权。同时 SAML 已被众多商家支持,可在规模庞大的环境中实现联邦身份管理。它尽可能详细地指定了绝大部分实际情况,从而提供了出色的交互性。对于独特的需求和未来可能出 现的需求而言,它还是可扩展的。