<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>My Pool &#187; design</title>
	<atom:link href="http://www.hlouis.com/category/design/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.hlouis.com</link>
	<description>Help, I can&#039;t swimming......</description>
	<lastBuildDate>Tue, 04 May 2010 15:27:10 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Script RPC</title>
		<link>http://www.hlouis.com/design/script-rpc/</link>
		<comments>http://www.hlouis.com/design/script-rpc/#comments</comments>
		<pubDate>Wed, 03 Dec 2008 06:30:52 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[design]]></category>
		<category><![CDATA[mess]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/?p=83</guid>
		<description><![CDATA[In c/c++ server design, event call always the painful part. How to register callback functions:

Use global or static method? 
Use event class and vritual method call?
How to handle the memory between caller and callee?
How to pass context, use pointer? use handle?

So many questions need to be taken care, but, maybe under the script world, life will [...]]]></description>
			<content:encoded><![CDATA[<p>In c/c++ server design, event call always the painful part. How to register callback functions:</p>
<ul>
<li>Use global or static method? </li>
<li>Use event class and vritual method call?</li>
<li>How to handle the memory between caller and callee?</li>
<li>How to pass context, use pointer? use handle?</li>
</ul>
<div>So many questions need to be taken care, but, maybe under the script world, life will be more easy&#8230;..</div>
<div></div>
<div>Lua thoughts:</div>
<div>
<ul>
<li>Use coroutines, when do an async call, we stop this coroutine, when callback, we resume the coroutine, so each context is there, we do not need pass anything, only the coroutine handler.</li>
<li>Functional languange easy to pass or generate callback function, so handler some very simple callback event, are very convenient.</li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/design/script-rpc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hard work with Soft work</title>
		<link>http://www.hlouis.com/design/hard-work-with-soft-work/</link>
		<comments>http://www.hlouis.com/design/hard-work-with-soft-work/#comments</comments>
		<pubDate>Wed, 23 Jan 2008 13:03:16 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/design/hard-work-with-soft-work/</guid>
		<description><![CDATA[前段时间转载过程序员的温情管理文化在 这篇文章中提出：
程序员是这样 一群家伙，他们可以把1000行代码写成10行，当然也可以把10行代码写成1000行。他们可以让这1000行代码比那10行容易看懂效率更高，也可以 让那10行比这1000行容易看懂效率更高。
我非常同意这样的看法，一个程序员如果在脑袋糊涂，精神萎靡的情况下写出代码 ，往往是逻辑不清楚，只是想把事情糊弄过去，久而久之，众多的小问题就积累起来，让整个项目陷入泥潭，并进入不得不重构的境地。
一个程序员，如果一天可以集中精力，进行5个小时以上的高效工作，并在这段时间内保持思路清楚，编写出高质量的代码，我觉得他肯定已经是顶级的程序员了，精力过人并且技术扎实。对于我们这样的正常人来说，一天可以维持三到四小时这样的高效工作就已经是很了不起的事情了。对于这段高效高质时间，我们应该加以充分的利用。对于效率偏低的时间，我们应该换一个策略来进行工作，这就是我想要说的，对于程序员的工作安排，应该有Hard word和Soft work的区分。
Hard work是指，列在工作项目上的，必须要做完的东西。这些工作项目都是列在整个开发项目的日程表上，不可或缺的环节。
Soft work是指，并没有列在整个项目的开发日程表上，但是对于技术储备，思路拓展都很有帮助的任务。进行Soft work应该可以让程序员enjoy其中，毕竟如果你对学习新技术没有兴趣，估计程序员的职业也就不适合你了。
对于项目的管理人员，挑战的任务就是如何分派两种任务，如何引导程序员进行Soft work，并控制这两种工作所需消耗的时间，如何帮助程序员了解并提高自己的高效工作时间，并可以让他们在早上打开电脑之后就能很明确的知道：今天的工作是什么，哪些最重要，哪些优先级别最高。
]]></description>
			<content:encoded><![CDATA[<p>前段时间转载过<a href="http://www.mypool.cn/diary/cheng-xu-yuan-guan-li/" rel="bookmark">程序员的温情管理文化</a>在 这篇文章中提出：</p>
<blockquote><p>程序员是这样 一群家伙，他们可以把1000行代码写成10行，当然也可以把10行代码写成1000行。他们可以让这1000行代码比那10行容易看懂效率更高，也可以 让那10行比这1000行容易看懂效率更高。</p></blockquote>
<p>我非常同意这样的看法，一个程序员如果在脑袋糊涂，精神萎靡的情况下写出代码 ，往往是逻辑不清楚，只是想把事情糊弄过去，久而久之，众多的小问题就积累起来，让整个项目陷入泥潭，并进入不得不重构的境地。</p>
<p>一个程序员，如果一天可以集中精力，进行5个小时以上的高效工作，并在这段时间内保持思路清楚，编写出高质量的代码，我觉得他肯定已经是顶级的程序员了，精力过人并且技术扎实。对于我们这样的正常人来说，一天可以维持三到四小时这样的高效工作就已经是很了不起的事情了。对于这段高效高质时间，我们应该加以充分的利用。对于效率偏低的时间，我们应该换一个策略来进行工作，这就是我想要说的，对于程序员的工作安排，应该有Hard word和Soft work的区分。</p>
<p>Hard work是指，列在工作项目上的，必须要做完的东西。这些工作项目都是列在整个开发项目的日程表上，不可或缺的环节。<br />
Soft work是指，并没有列在整个项目的开发日程表上，但是对于技术储备，思路拓展都很有帮助的任务。进行Soft work应该可以让程序员enjoy其中，毕竟如果你对学习新技术没有兴趣，估计程序员的职业也就不适合你了。</p>
<p>对于项目的管理人员，挑战的任务就是如何分派两种任务，如何引导程序员进行Soft work，并控制这两种工作所需消耗的时间，如何帮助程序员了解并提高自己的高效工作时间，并可以让他们在早上打开电脑之后就能很明确的知道：今天的工作是什么，哪些最重要，哪些优先级别最高。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/design/hard-work-with-soft-work/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[ZT]MMORPG Server Design</title>
		<link>http://www.hlouis.com/design/ztmmorpg-server-design/</link>
		<comments>http://www.hlouis.com/design/ztmmorpg-server-design/#comments</comments>
		<pubDate>Mon, 17 Dec 2007 02:38:10 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/design/ztmmorpg-server-design/</guid>
		<description><![CDATA[转载自 http://www.cppblog.com/Fox/archive/2007/12/16/38600.html
这篇文章转载自Fox的研究论文的开题报告，写的比较细致，和我目前所做得工作也比较相似。不过行文的水平比我高，把很多我说不明白的事情都表达了出来。很多具体的问题没还有深入，期待后续的文章



Author: Fox(yulefox@126.com)

一个MMORPG（Massively Multiplayer Online Role Playing Game）的架构包含客户端和服务器两部分。客户端主要涉及计算机图形学、物理学、多媒体技术等，服务器主要涉及网络通信技术、数据库技术，而人工智能、操作系统等计算机基础学科知识的应用体现在MMORPG开发过程中的方方面面。

一、游戏世界的划分
理想状态的游戏世界仅由一个完整的场景组成，在《魔兽争霸III》、《CS》这样的单机游戏中，所有玩家位于该场景中，在理论上，位于该场景中的任意玩家都可以看到游戏中所有玩家并与之交互，出于公平性和游戏性（而不是技术上）的考虑，游戏中并不会这样做。
然而，目前的MMORPG中，几乎没有任何一款可以做到整个游戏世界只包含一个场景，因为在一款MMORPG中，同时在线的玩家数量成百上千，甚至是数万人同时在一个游戏世界中交互。以现在的网络技术和计算机系统，还无法为这么多玩家的交互提供即时处理。因此，MMORPG的游戏世界被划分为大小不等、数量众多的场景，游戏服务器对于这些场景的处理分为分区和无缝两种。
在分区式服务器中，一个场景中的玩家无法看到另一个场景中的玩家，当玩家从一个场景到另外一个场景跨越时，都有一个数据转移和加载的过 程（尤其是从一个分区服务器跨越到另外一个服务器时），玩家都有一个等待的时间，在这段时间内，服务器的主要工作是实现跨越玩家数据的转移和加载以及后一 个场景中玩家、NPC等数据的传输，客户端的主要工作是实现新场景资源的加载和服务器通信。主要时 间的长短主要取决于后一个场景中资源数据的大小。分区式服务器的优点主要是各分区服务器保持相对独立，缺点是游戏空间不够大，而且，一旦某个分区服务器中 止服务，位于该服务器上的所有玩家将失去连接。
所谓无缝服务器，玩家几乎察觉不到场景之间的这种切换，在场景间没有物理上的屏障，对于玩家而言，众多场景构成了一个巨大的游戏世界。 场景之间，甚至服务器之间“没有了”明确的界线。因此，无缝服务器为玩家提供了更大的游戏空间和更友好的交互，实现了动态边界的无缝服务器甚至可以在某个 服务器中止服务时，按一定策略将负载动态分散到其他服务器。因此，无缝服务器在技术上要比分区服务器更加复杂。
目前国内上市的MMORPG，大多采用分区式服务器，做到无缝世界的主要有《完美世界》和《天下贰》等，国外的MMORPG中，像《魔兽世界》、《EVE》等，都实现了无缝世界。
无缝服务器与分区式服务器在技术上的主要区别是，当位于场景S1中的玩家P1处于两个（甚至更多）场景S1、S2的边界区域内时，要保证P1能够看到场景S2中建筑、玩家、NPC等可感知对象。而且边界区域的大小要大于等于P1可感知的范围，否则就可能发生S2中的可感知对象突然闪现在P1视野中的异常。
无疑，无缝世界为玩家提供了更人性化和更具魅力的用户体验。
二、无缝世界游戏服务器的整体架构
MMORPG的服务器架构从功能上主要划分为三种：
1、登录服务器（Login Server）
登录服务器用于玩家验证登录，并根据系统记录玩家信息得到其所在节点服务器，并通过世界服务器为登录玩家和对应节点服务器建立连接。
2、世界服务器（World Server）
世界服务器将整个游戏世界划分成不同场景，将所有场景按一定策略分配给节点服务器，并对节点服务器进行管理。世界服务器的另一功能是与 登录服务器交互。因此，世界服务器是登录服务器、节点服务器的沟通桥梁，当然，一旦玩家登录成功，世界服务器将主要处理节点服务器间的通信。因此，世界服 务器对于玩家是透明的。
3、节点服务器（Node Server）
节点服务器负责管理位于该节点的所有玩家、NPC的所有交互，在无缝世界游戏中，由于边界区域的存在，一个节点服务器甚至要处理相邻节点上位于边界区域的玩家和NPC的信息。
在具体实现上，不同的MMORPG为了便于管理，可能还会具有AI服务器、日志服务器、数据库缓存服务器、代理服务器等。
三、无缝世界游戏服务器的主要技术需求
1、编程语言（C/C++、SQL、Lua、Python）
2、图形库（Direct 3D、OpenGL）
3、网络通信（WinSock、BSD Socket，或者ACE）
4、消息、事件、多线程、GUI
5、OS
三、无缝世界游戏服务器需要解决的主要问题
1、资源管理
无论是服务器还是客户端，都涉及到大量资源：玩家数据、NPC数据、战斗公式、模型资源、通信资源等。当这些资源达到一定规模，其管理的难度不可忽视。而且，资源管理的好坏，直接关系到游戏的安全和生命。
2、网络安全
安全永远是第一位的，我们无法指望所有的玩家及其所持的客户端永远是友好的。事实上，威胁到游戏的公平性和安全性的大多数问题，归根结底，都是由于网络通信中存在的欺骗和攻击造成的，这些问题包含但不限于交易欺骗、物品复制。
3、逻辑安全
逻辑安全按理说应该是游戏中最基本的考虑，覆盖的范围也最广最杂。随机数系统是一个非常值得重视的问题，随机数不仅仅用于玩家可见的一 些任务系统、战斗公式、人工智能、物品得失等，还可用于网络报文加密等。因此，随机数系统本身的安全不容忽视。另外一个常见的逻辑安全是玩家的移动，最主 要的就是防止加速齿轮这样的变态操作。
4、负载均衡
MMORPG中的负载均衡包括客户端及服务器资源管理和逻辑处理的负载均衡，其中最难预知的是网络通信的负 载均衡，正常情况下的网络通信数量是可以在游戏设计时做出评估的，但因恶意攻击造成的网络负载是无法预测的。因此，负载均衡所要处理的主要是实时动态负载 均衡和灾难恢复。负载均衡需要解决的问题包括负载监控、负载分析、负载分发和灾难恢复。
5、录像系统
录像系统的构建，主要用于重现关键数据的输入输出，如玩家交易、玩家充值，或者当bug出现后，为逻辑服务器（泛指上文提到的所有类型服务器，主要是节点服务器）相应部分启动录像系统。待收集到足够数据后，通过录像系统重现bug。为了使逻辑服务器不受自身时间（如中断调试等）的影响，还可以专门设计心跳服务器来控制数据传输。
四、总结
在MMORPG中，真正的bug永远存在于将来。从这一点出发，关于MMORPG中游戏世界的构建，怎样苛刻的思考都不为过。
参考资料：
1、 [美] Kim Pallister编, 孟宪武 等译. 游戏编程精粹5, P467-474, P516. 人民邮电出版社, 2007年9月. 北京.
2、 [美] Thor Alexander编, 史晓明 译. 大型多人在线游戏开发, P174-185. 人民邮电出版社, 2006年12月. 北京.
3、 [美] Dante Treglia编, 张磊 译. 游戏编程精粹3, P117-122. 人民邮电出版社, 2003年7月. [...]]]></description>
			<content:encoded><![CDATA[<p>转载自 <a href="http://www.cppblog.com/Fox/archive/2007/12/16/38600.html">http://www.cppblog.com/Fox/archive/2007/12/16/38600.html</a></p>
<p>这篇文章转载自Fox的研究论文的开题报告，写的比较细致，和我目前所做得工作也比较相似。不过行文的水平比我高，把很多我说不明白的事情都表达了出来。很多具体的问题没还有深入，期待后续的文章</p>
<p></p>
<hr />
</p>
<p>Author: Fox(<a href="mailto:yulefox@126.com" target="_blank">yulefox@126.com</a>)<br />
<span><br />
一个</span><span>MMORPG</span><span>（</span><span>Massively Multiplayer Online Role Playing Game</span><span>）的架构包含客户端和服务器两部分。客户端主要涉及计算机图形学、物理学、多媒体技术等，服务器主要涉及网络通信技术、数据库技术，而人工智能、操作系统等计算机基础学科知识的应用体现在</span><span>MMORPG</span><span>开发过程中的方方面面。</span></p>
<p><span id="more-74"></span></p>
<p><span>一、游戏世界的划分</span></p>
<p><span>理想状态的游戏世界仅由一个完整的场景组成，在《魔兽争霸</span><span>III</span><span>》、《</span><span>CS</span><span>》这样的单机游戏中，所有玩家位于该场景中，在理论上，位于该场景中的任意玩家都可以看到游戏中所有玩家并与之交互，出于公平性和游戏性（而不是技术上）的考虑，游戏中并不会这样做。</span></p>
<p><span>然而，目前的</span><span>MMORPG</span><span>中，几乎没有任何一款可以做到整个游戏世界只包含一个场景，因为在一款</span><span>MMORPG</span><span>中，同时在线的玩家数量成百上千，甚至是数万人同时在一个游戏世界中交互。以现在的网络技术和计算机系统，还无法为这么多玩家的交互提供即时处理。因此，</span><span>MMORPG</span><span>的游戏世界被划分为大小不等、数量众多的场景，游戏服务器对于这些场景的处理分为分区和无缝两种。</span></p>
<p><span>在分区式服务器中，一个场景中的玩家无法看到另一个场景中的玩家，当玩家从一个场景到另外一个场景跨越时，都有一个数据转移和加载的过 程（尤其是从一个分区服务器跨越到另外一个服务器时），玩家都有一个等待的时间，在这段时间内，服务器的主要工作是实现跨越玩家数据的转移和加载以及后一 个场景中玩家、</span><span>NPC</span><span>等数据的传输，客户端的主要工作是实现新场景资源的加载和服务器通信。主要时 间的长短主要取决于后一个场景中资源数据的大小。分区式服务器的优点主要是各分区服务器保持相对独立，缺点是游戏空间不够大，而且，一旦某个分区服务器中 止服务，位于该服务器上的所有玩家将失去连接。</span></p>
<p><span>所谓无缝服务器，玩家几乎察觉不到场景之间的这种切换，在场景间没有物理上的屏障，对于玩家而言，众多场景构成了一个巨大的游戏世界。 场景之间，甚至服务器之间“没有了”明确的界线。因此，无缝服务器为玩家提供了更大的游戏空间和更友好的交互，实现了动态边界的无缝服务器甚至可以在某个 服务器中止服务时，按一定策略将负载动态分散到其他服务器。因此，无缝服务器在技术上要比分区服务器更加复杂。</span></p>
<p><span>目前国内上市的</span><span>MMORPG</span><span>，大多采用分区式服务器，做到无缝世界的主要有《完美世界》和《天下贰》等，国外的</span><span>MMORPG</span><span>中，像《魔兽世界》、《</span><span>EVE</span><span>》等，都实现了无缝世界。</span></p>
<p><span>无缝服务器与分区式服务器在技术上的主要区别是，当位于场景</span><span>S1</span><span>中的玩家</span><span>P1</span><span>处于两个（甚至更多）场景</span><span>S1</span><span>、</span><span>S2</span><span>的边界区域内时，要保证</span><span>P1</span><span>能够看到场景</span><span>S2</span><span>中建筑、玩家、</span><span>NPC</span><span>等可感知对象。而且边界区域的大小要大于等于</span><span>P1</span><span>可感知的范围，否则就可能发生</span><span>S2</span><span>中的可感知对象突然闪现在</span><span>P1</span><span>视野中的异常。</span></p>
<p><span>无疑，无缝世界为玩家提供了更人性化和更具魅力的用户体验。</span></p>
<p><span>二、无缝世界游戏服务器的整体架构</span></p>
<p><span>MMORPG</span><span>的服务器架构从功能上主要划分为三种：</span></p>
<p><span><span>1、</span></span><span>登录服务器（</span><span>Login Server</span><span>）</span></p>
<p><span>登录服务器用于玩家验证登录，并根据系统记录玩家信息得到其所在节点服务器，并通过世界服务器为登录玩家和对应节点服务器建立连接。</span></p>
<p><span><span>2、</span></span><span>世界服务器（</span><span>World Server</span><span>）</span></p>
<p><span>世界服务器将整个游戏世界划分成不同场景，将所有场景按一定策略分配给节点服务器，并对节点服务器进行管理。世界服务器的另一功能是与 登录服务器交互。因此，世界服务器是登录服务器、节点服务器的沟通桥梁，当然，一旦玩家登录成功，世界服务器将主要处理节点服务器间的通信。因此，世界服 务器对于玩家是透明的。</span></p>
<p><span><span>3、</span></span><span>节点服务器（</span><span>Node Server</span><span>）</span></p>
<p><span>节点服务器负责管理位于该节点的所有玩家、</span><span>NPC</span><span>的所有交互，在无缝世界游戏中，由于边界区域的存在，一个节点服务器甚至要处理相邻节点上位于边界区域的玩家和</span><span>NPC</span><span>的信息。</span></p>
<p><span>在具体实现上，不同的</span><span>MMORPG</span><span>为了便于管理，可能还会具有</span><span>AI</span><span>服务器、日志服务器、数据库缓存服务器、代理服务器等。</span></p>
<p><span><span>三、</span></span><span>无缝世界游戏服务器的主要技术需求</span></p>
<p><span><span>1、</span></span><span>编程语言（</span><span>C/C++</span><span>、</span><span>SQL</span><span>、</span><span>Lua</span><span>、</span><span>Python</span><span>）</span></p>
<p><span><span>2、</span></span><span>图形库（</span><span>Direct 3D</span><span>、</span><span>OpenGL</span><span>）</span></p>
<p><span><span>3、</span></span><span>网络通信（</span><span>WinSock</span><span>、</span><span>BSD Socket</span><span>，或者</span><span>ACE</span><span>）</span></p>
<p><span><span>4、</span></span><span>消息、事件、多线程、</span><span>GUI</span></p>
<p><span><span>5、</span></span><span>OS</span></p>
<p><span>三、无缝世界游戏服务器需要解决的主要问题</span></p>
<p><span><span>1、</span></span><span>资源管理</span></p>
<p><span>无论是服务器还是客户端，都涉及到大量资源：玩家数据、</span><span>NPC</span><span>数据、战斗公式、模型资源、通信资源等。当这些资源达到一定规模，其管理的难度不可忽视。而且，资源管理的好坏，直接关系到游戏的安全和生命。</span></p>
<p><span><span>2、</span></span><span>网络安全</span></p>
<p><span>安全永远是第一位的，我们无法指望所有的玩家及其所持的客户端永远是友好的。事实上，威胁到游戏的公平性和安全性的大多数问题，归根结底，都是由于网络通信中存在的欺骗和攻击造成的，这些问题包含但不限于交易欺骗、物品复制。</span></p>
<p><span><span>3、</span></span><span>逻辑安全</span></p>
<p><span>逻辑安全按理说应该是游戏中最基本的考虑，覆盖的范围也最广最杂。随机数系统是一个非常值得重视的问题，随机数不仅仅用于玩家可见的一 些任务系统、战斗公式、人工智能、物品得失等，还可用于网络报文加密等。因此，随机数系统本身的安全不容忽视。另外一个常见的逻辑安全是玩家的移动，最主 要的就是防止加速齿轮这样的变态操作。</span></p>
<p><span><span>4、</span></span><span>负载均衡</span></p>
<p><span>MMORPG</span><span>中的负载均衡包括客户端及服务器资源管理和逻辑处理的负载均衡，其中最难预知的是网络通信的负 载均衡，正常情况下的网络通信数量是可以在游戏设计时做出评估的，但因恶意攻击造成的网络负载是无法预测的。因此，负载均衡所要处理的主要是实时动态负载 均衡和灾难恢复。负载均衡需要解决的问题包括负载监控、负载分析、负载分发和灾难恢复。</span></p>
<p><span><span>5、</span></span><span>录像系统</span></p>
<p><span>录像系统的构建，主要用于重现关键数据的输入输出，如玩家交易、玩家充值，或者当</span><span>bug</span><span>出现后，为逻辑服务器（泛指上文提到的所有类型服务器，主要是节点服务器）相应部分启动录像系统。待收集到足够数据后，通过录像系统重现</span><span>bug</span><span>。为了使逻辑服务器不受自身时间（如中断调试等）的影响，还可以专门设计心跳服务器来控制数据传输。</span></p>
<p><span>四、总结</span></p>
<p><span>在</span><span>MMORPG</span><span>中，真正的</span><span>bug</span><span>永远存在于将来。从这一点出发，关于</span><span>MMORPG</span><span>中游戏世界的构建，怎样苛刻的思考都不为过。</span></p>
<p>参考资料：</p>
<p><span>1、 [美] Kim Pallister编, 孟宪武 等译. 游戏编程精粹5, P467-474, P516. 人民邮电出版社, 2007年9月. 北京.<br />
2、 [美] Thor Alexander编, 史晓明 译. 大型多人在线游戏开发, P174-185. 人民邮电出版社, 2006年12月. 北京.<br />
3、 [美] Dante Treglia编, 张磊 译. 游戏编程精粹3, P117-122. 人民邮电出版社, 2003年7月. 北京.<br />
4、 [美] Mark DeLoura编, 王淑礼 等译. 游戏编程精粹1, P90-93. 人民邮电出版社, 2004年10月. 北京.<br />
5、 [美] Douglas 等著, 於春景 译. C++网络编程 卷1. 中国电力出版社, 2004年11月. 北京.<br />
6、 [美] Stephen D. Huston 等著, 马维达 译. ACE程序员指南. 中国电力出版社, 2004年11月. 北京.<br />
7、 [美] Erich Gamma等著, 李英军 等译. 设计模式. 机械工业出版社, 2000年6月. 北京.<br />
8、 游戏引擎全剖析. <a href="http://bbs.gameres.com/showthread.asp?threadid=101293" target="_blank">http://bbs.gameres.com/showthread.asp?threadid=101293</a>.<br />
9、 服务器结构探讨：登录服的负载均衡. <a href="http://gamedev.csdn.net/page/351491d0-05ad-48a4-85e1-77870bc1eef3" target="_blank">http://gamedev.csdn.net/page/351491d0-05ad-48a4-85e1-77870bc1eef3</a>.<br />
10、服务器结构探讨：最终的结构. <a href="http://gamedev.csdn.net/page/28695655-974c-4291-8ac4-2589c4e770d3" target="_blank">http://gamedev.csdn.net/page/28695655-974c-4291-8ac4-2589c4e770d3</a>.<br />
11、谈谈网络游戏服务器解决方案. <a href="http://www.beareyes.com.cn/2/lib/200411/08/20041108102.htm" target="_blank">http://www.beareyes.com.cn/2/lib/200411/08/20041108102.htm</a>.<br />
12、负载均衡——大型在线系统实现的关键(下篇)（服务器集群架构的设计与选择）. <a href="http://blog.csdn.net/sodme/archive/2005/06/15/394576.aspx" target="_blank">http://blog.csdn.net/sodme/archive/2005/06/15/394576.aspx</a>.<br />
13、云风的BLOG. <a href="http://blog.codingnow.com/" target="_blank">http://blog.codingnow.com/</a><br />
</span></p>
<p><span style="color: #008000">/*****************************************************************************<br />
从0:00到5:00，在写这篇随笔的过程中，我翻找、点击着上面的这些资料，其实还有更<br />
多的资料，没有记在上面，算是为开题做的准备。现在依然是睡意全无。越写越觉得<br />
不够，越想越觉得还有更多东西写不出来……<br />
PS：这些资料大都不是第一次翻，以前看这些资料大多只是单纯的看，现在有目的的<br />
看，才觉得都写得很有味道。不管是不是同意所有观点，都不是本文讨论的重点。<br />
*****************************************************************************/</span>  <img src="http://www.cppblog.com/Fox/aggbug/38600.html" height="1" width="1" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/design/ztmmorpg-server-design/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Expose inside design</title>
		<link>http://www.hlouis.com/design/expose-inside-design/</link>
		<comments>http://www.hlouis.com/design/expose-inside-design/#comments</comments>
		<pubDate>Thu, 06 Dec 2007 07:56:59 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/design/expose-inside-design/</guid>
		<description><![CDATA[有些时候，UI的一个设计准则就是将程序内部的设计结构暴露出来给用户，比如Mac系统上很流行的一个tap-to-run的程序，Quicksilver，一个基于键盘的程序启动软件，它的基本界面如下：

如上所见，左边是Quicksilver根据我让键入的字符在系统中寻找到的对象，右边就是针对这个对象所做的动作，用户可以使用默认动作或者是使用其他的动作。例如针对一个文本文件就有预览，打开等动作。
没有看过Quicksilver的代码，不过相信要我做一个这样的类似程序，我也一定会做这样的内部设计：
对象 &#8212; 动作
将对象和动作分别封装成两种最基础的类型，让他们之间有一定的属性可以互相交互从而形成关联。对于程序设计者来说，这个可能是最基础的想法。Quicksilver也忠实的将这个想法反应到UI上。程序设计师对于软件的理解肯定要比一般的使用者深入，如果我们能将一个好的设计暴露到UI上，往往可以给普通用户带来更好的体验。
]]></description>
			<content:encoded><![CDATA[<p>有些时候，UI的一个设计准则就是将程序内部的设计结构暴露出来给用户，比如Mac系统上很流行的一个tap-to-run的程序，Quicksilver，一个基于键盘的程序启动软件，它的基本界面如下：</p>
<p><img src="http://www.hlouis.com/hlouis_com/wp-content/uploads/2007/12/0_quicksilver001.jpg" alt="Quicksilver" /></p>
<p>如上所见，左边是Quicksilver根据我让键入的字符在系统中寻找到的对象，右边就是针对这个对象所做的动作，用户可以使用默认动作或者是使用其他的动作。例如针对一个文本文件就有预览，打开等动作。</p>
<p>没有看过Quicksilver的代码，不过相信要我做一个这样的类似程序，我也一定会做这样的内部设计：</p>
<blockquote><p>对象 &#8212; 动作</p></blockquote>
<p>将对象和动作分别封装成两种最基础的类型，让他们之间有一定的属性可以互相交互从而形成关联。对于程序设计者来说，这个可能是最基础的想法。Quicksilver也忠实的将这个想法反应到UI上。程序设计师对于软件的理解肯定要比一般的使用者深入，如果我们能将一个好的设计暴露到UI上，往往可以给普通用户带来更好的体验。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/design/expose-inside-design/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Game data server draft design</title>
		<link>http://www.hlouis.com/design/game-data-server-draft-design/</link>
		<comments>http://www.hlouis.com/design/game-data-server-draft-design/#comments</comments>
		<pubDate>Mon, 26 Nov 2007 13:22:14 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/design/game-data-server-draft-design/</guid>
		<description><![CDATA[游戏数据服务器是什么
数据服务器，一下简称DS，用来保存游戏中的数据，他存在与持久层之上，逻辑层之下，是一个针对逻辑层的数据持久层。
为什么需要这层
在我开发游戏服务器以来，发现的一个最严重的问题就是，游戏数据的安全和正确。对于游戏的数据我们大体可以分出一下两类：

临时数据：由游戏运行时生成，无需进行保存。在玩家下线或游戏服务器关闭之后就可以抛弃。
持久数据：游戏人物的数据、游戏中的物品，人物排名等等由玩家或服务器创造出的并有保存价值的数据

对于一款网络游戏来说，数据基本上是一切。玩家丢了数据等于是被盗号，运营商如果丢了很多玩家的数据基本上就无法正常的运营下去。对于数据可能出现的问题如下：

数据回档：档的原因多种多样， 大体有以下的原因：

服务器崩溃导致距离上次存档的数据没有保存
人物数据错乱，导致游戏无法将该玩家的数据保存（和数据库中的某些限制出现冲突）


数据存储效率低下，导致玩家存储数据的时间长于每次存储的间隙
游戏中的物品产生复制，在游戏中的交易的双方交易后出现某一方的回档，物品就会出现复制
数据保存复杂、危险，由于程序员的大量开发工作主要针对于服务器的逻辑，如果需要兼顾撰写保存数据的SQL，很可能出现问题

针对游戏服务器的数据的重要性和易错性，我觉得非常需要添加一层数据层，使游戏数据库对游戏服务器的逻辑透明，同时提供一些简单的方法保证数据的一致性。
具体要求
针对以上的分析，我觉得一个合格的DS需要做到一下的条目：

使SQL对使用者透明：
在这里我们假设，数据库的最终保存持久层依然是某种数据库，那么DS因该可以使用定义的数据类型自动生成保存，更新和读取的SQL语言。撰写逻辑的程序员，只需要定义数据类型和结构，完全不需要考虑和数据库的操作。数据库对于游戏逻辑程序员来说是完全透明的。
数据需要有权限概念：
第一个对某个数据进行访问的用户（其他的游戏逻辑服务器）是该数据的拥有者，拥有者可以限制其他访问者对该数据的权限，是否可读，是否可写等。同时拥有权可以放弃或移交。
支持对数据的原子操作：
对于交易等数据操作，可能需要同时更新两个以上的数据单元，这时候需要提供原子操作的支持，如果某个数据单元的更新不成功，就要让整个操作回滚。
DS本身的稳定以及自我恢复：
DS本身的逻辑应该足够简单，并保证服务稳定，内存占用合理并可以在配置文件中调整。DS如果发现持久层出现错误，比如无法连接到数据库，可以通知客户终止操作，并将当前DS内存的数据dump到本地文件，等待问题修正后可以重新Load到内存中。
多个DS的分布处理：
由于DS的内存和效率等的限制，对于一个游戏应用来说，一个DS可能无法承担所有的应用，需要考虑DS的分布处理。分布处理可能会涉及到很多细节，导致复杂度大大增加，希望有时间，我可以继续讨论这个问题。

]]></description>
			<content:encoded><![CDATA[<h2>游戏数据服务器是什么</h2>
<p>数据服务器，一下简称DS，用来保存游戏中的数据，他存在与持久层之上，逻辑层之下，是一个针对逻辑层的数据持久层。</p>
<h2>为什么需要这层</h2>
<p>在我开发游戏服务器以来，发现的一个最严重的问题就是，游戏数据的安全和正确。对于游戏的数据我们大体可以分出一下两类：</p>
<ul>
<li>临时数据：由游戏运行时生成，无需进行保存。在玩家下线或游戏服务器关闭之后就可以抛弃。</li>
<li>持久数据：游戏人物的数据、游戏中的物品，人物排名等等由玩家或服务器创造出的并有保存价值的数据</li>
</ul>
<p>对于一款网络游戏来说，数据基本上是一切。玩家丢了数据等于是被盗号，运营商如果丢了很多玩家的数据基本上就无法正常的运营下去。对于数据可能出现的问题如下：</p>
<ol>
<li>数据回档：档的原因多种多样， 大体有以下的原因：
<ol>
<li>服务器崩溃导致距离上次存档的数据没有保存</li>
<li>人物数据错乱，导致游戏无法将该玩家的数据保存（和数据库中的某些限制出现冲突）</li>
</ol>
</li>
<li>数据存储效率低下，导致玩家存储数据的时间长于每次存储的间隙</li>
<li>游戏中的物品产生复制，在游戏中的交易的双方交易后出现某一方的回档，物品就会出现复制</li>
<li>数据保存复杂、危险，由于程序员的大量开发工作主要针对于服务器的逻辑，如果需要兼顾撰写保存数据的SQL，很可能出现问题</li>
</ol>
<p>针对游戏服务器的数据的重要性和易错性，我觉得非常需要添加一层数据层，使游戏数据库对游戏服务器的逻辑透明，同时提供一些简单的方法保证数据的一致性。</p>
<h2>具体要求</h2>
<p>针对以上的分析，我觉得一个合格的DS需要做到一下的条目：</p>
<ul>
<li>使SQL对使用者透明：<br />
在这里我们假设，数据库的最终保存持久层依然是某种数据库，那么DS因该可以使用定义的数据类型自动生成保存，更新和读取的SQL语言。撰写逻辑的程序员，只需要定义数据类型和结构，完全不需要考虑和数据库的操作。数据库对于游戏逻辑程序员来说是完全透明的。</li>
<li>数据需要有权限概念：<br />
第一个对某个数据进行访问的用户（其他的游戏逻辑服务器）是该数据的拥有者，拥有者可以限制其他访问者对该数据的权限，是否可读，是否可写等。同时拥有权可以放弃或移交。</li>
<li>支持对数据的原子操作：<br />
对于交易等数据操作，可能需要同时更新两个以上的数据单元，这时候需要提供原子操作的支持，如果某个数据单元的更新不成功，就要让整个操作回滚。</li>
<li>DS本身的稳定以及自我恢复：<br />
DS本身的逻辑应该足够简单，并保证服务稳定，内存占用合理并可以在配置文件中调整。DS如果发现持久层出现错误，比如无法连接到数据库，可以通知客户终止操作，并将当前DS内存的数据dump到本地文件，等待问题修正后可以重新Load到内存中。</li>
<li>多个DS的分布处理：<br />
由于DS的内存和效率等的限制，对于一个游戏应用来说，一个DS可能无法承担所有的应用，需要考虑DS的分布处理。分布处理可能会涉及到很多细节，导致复杂度大大增加，希望有时间，我可以继续讨论这个问题。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/design/game-data-server-draft-design/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>多服务器的用户身份认证方案</title>
		<link>http://www.hlouis.com/design/kerberos-yunfen/</link>
		<comments>http://www.hlouis.com/design/kerberos-yunfen/#comments</comments>
		<pubDate>Tue, 13 Nov 2007 03:26:06 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/design/kerberos-yunfen/</guid>
		<description><![CDATA[&#160;
转自云风
当游戏服务器群达到一定规模后，让用户只从一个入口连入会给这个入口带来很大的压力。这样，我们就需要让服务器群中的多台机器都允许用户直接连接。
当服务器开放给用户直接登陆后，必须面临的一个问题就是用户身份认证的问题。
大多数提供网络服务的公司都做了一套统一的用户认证系统，比如微软的 passport ，网易的通行证，等等。为了避免重复验证用户身份而给用户认证系统带来过大的负担，云风在这里给出一个参考解决方案。
登陆服务器可以只有一台，专门用于用户第一次登陆的身份认证。它认证完用户的身份后，则发放一个游戏系统内部用的临时通行证给用户，用户可以拿着这个临时通行证到指定的地点玩游戏。
我们需要讨论的是，以上流程中的安全问题，以及如何加强安全性。
用户认证过程自然不能传送用户密码的全部信息，这跟密码是否加密无关。简单的安全措施是先由登陆服务器发送一个随机串给用户，用户把这个字符串同自己的密码连接起来，并 md5 以后传回服务器做验证。（这里用 md5 指代一种特定的不可逆 hash 算法）
临时通行证的生成可以是这样： 登陆服务器从数据库中取得用户所属的服务器 id （通常是他最后一次登陆的位置，或者游戏逻辑认为他所在位置）、用户的游戏 id （往往不同于他的用户名）、一个约定字符串、一个顺序版本号、一些随机字节、把它们连在作一次 des 加密（这里用 des 指代一种特定的可逆密匙加密算法）。每生成一次临时通行证，版本号递增。加密临时通行证的密码由登陆服务器与每个可以接受用户直接连接的服务器约定，永远 不传送给用户。
用户拿到这个临时通行证后，可以用之一次性登陆指定服务器。直到从服务器正常登出，若需切入新服务器，可由老服务器生成下一份临时通行证。临时通行证由于被服务器加密，所以对用户来说是一串无意义字符串，故而无法伪造。
临时通行证传送给用户时，可用用户自己的密码之 md5 值（或者连接一个约定串增加安全性）做密匙加密。这样不知道密匙的人截获数据包也不能获得临时身份证。而临时身份证总是一次有效，且只针对特定服务器（服 务器会检查临时通行证中包含的版本号、服务器 id ），企图用临时身份证多次登陆也会失败。
]]></description>
			<content:encoded><![CDATA[<p class="entry-content">&nbsp;</p>
<p class="entry-body"><a href="http://blog.codingnow.com/2007/02/user_authenticate.html">转自云风</a></p>
<p class="entry-body">当游戏服务器群达到一定规模后，让用户只从一个入口连入会给这个入口带来很大的压力。这样，我们就需要让服务器群中的多台机器都允许用户直接连接。</p>
<p>当服务器开放给用户直接登陆后，必须面临的一个问题就是用户身份认证的问题。</p>
<p>大多数提供网络服务的公司都做了一套统一的用户认证系统，比如微软的 passport ，网易的通行证，等等。为了避免重复验证用户身份而给用户认证系统带来过大的负担，云风在这里给出一个参考解决方案。</p>
<p id="more" class="entry-more">登陆服务器可以只有一台，专门用于用户第一次登陆的身份认证。它认证完用户的身份后，则发放一个游戏系统内部用的临时通行证给用户，用户可以拿着这个临时通行证到指定的地点玩游戏。</p>
<p>我们需要讨论的是，以上流程中的安全问题，以及如何加强安全性。</p>
<p>用户认证过程自然不能传送用户密码的全部信息，这跟密码是否加密无关。简单的安全措施是先由登陆服务器发送一个随机串给用户，用户把这个字符串同自己的密码连接起来，并 md5 以后传回服务器做验证。（这里用 md5 指代一种特定的不可逆 hash 算法）</p>
<p>临时通行证的生成可以是这样： 登陆服务器从数据库中取得用户所属的服务器 id （通常是他最后一次登陆的位置，或者游戏逻辑认为他所在位置）、用户的游戏 id （往往不同于他的用户名）、一个约定字符串、一个顺序版本号、一些随机字节、把它们连在作一次 des 加密（这里用 des 指代一种特定的可逆密匙加密算法）。每生成一次临时通行证，版本号递增。加密临时通行证的密码由登陆服务器与每个可以接受用户直接连接的服务器约定，永远 不传送给用户。</p>
<p>用户拿到这个临时通行证后，可以用之一次性登陆指定服务器。直到从服务器正常登出，若需切入新服务器，可由老服务器生成下一份临时通行证。临时通行证由于被服务器加密，所以对用户来说是一串无意义字符串，故而无法伪造。</p>
<p>临时通行证传送给用户时，可用用户自己的密码之 md5 值（或者连接一个约定串增加安全性）做密匙加密。这样不知道密匙的人截获数据包也不能获得临时身份证。而临时身份证总是一次有效，且只针对特定服务器（服 务器会检查临时通行证中包含的版本号、服务器 id ），企图用临时身份证多次登陆也会失败。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/design/kerberos-yunfen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Kerberos的原理 &#8211; MIT</title>
		<link>http://www.hlouis.com/design/kerberos-basic/</link>
		<comments>http://www.hlouis.com/design/kerberos-basic/#comments</comments>
		<pubDate>Tue, 13 Nov 2007 03:24:12 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/design/kerberos-basic/</guid>
		<description><![CDATA[Kerberos是一个重要的认证协议,它为互不相识的通信双方做安全的认证工作。Kerberos这个名字的原义是希腊神话中守卫冥王大门的长有三头的看门狗。下面这篇Kerberos的文章不知是哪位老大翻译的，感谢先！
这是MIT（Massachusetts Institute of Technology）为了帮助人们理解Kerberos的原理而写的一篇对话集。里面有两个虚构的人物：Athena和Euripides，通过 Athena不断的构思和Euripides不断的寻找其中的漏洞，使大家明白了Kerberos协议的原理。
Athena: 雅典娜，智慧与技艺的女神。
Euripides:欧里庇得斯, 希腊的悲剧诗人。
译文如下：
第一幕
在一个小工作间里。Athena和Euripides正在相邻的终端上工作。
Athena: 嗨，这个分时操作系统实在太慢了。我根本无法工作，因为每个人都登上去了。
Euripides: 不要对我报怨。我只是在这工作。
Athena: 你知道我们需要什么吗？我们需要给每一个人一台工作，这样大家就不会担心计算机的速度了。并且，我们需要一个网络把所有的计算机都联起来。
Euripides: 好。那么我们差不多要一千台工作站？
Athena: 差不多吧。
Euripides: 你知道一台普通的工作站的硬盘有多大吗？那里放不下所有的软件。
Athena: 我已经有主意了。我们可以把系统软件放到服务器上。当你登录到工作站的时候，工作站会通过网络与其中一台服务器上的系统软件联系。这样的设置让一组工作站都使用同一份系统软件，并且利于系统软件的升級。只需改动服务器就可以了。
Euripides: 好的。个人的文件怎到办呢？在分时操作系统上，我可以登录并从终端上取走我的文件。我能到工作站上取我的文件吗？我要象PC用户一样把我的文件放到磁盘上去吗？我希望不。
Athena: 我想我们可以其它机器来存文件。你可以到任何一台机器上登录去取你的文件。
Euripides: 打印怎么办呢？每个工作站都要有自已的打印机吗？谁来付钱？电子邮件呢？你怎么把邮件送到所有的工作站上去呢？
Athena: 啊&#8230;..很明显我们没钱为每个人配一台打印机，但我们有专门的机器做打印服务。你把请求送到服务器，它就为你打印。邮件也可以这样做。专门有一台邮件服务器。你如果想要你的邮件，就联系邮件服务器，取走你的邮件。
Euripides: 你的工作站系统听起来很不错。如果我有一台，你知道我要做什么吗？我要找出你的用户名，让我的工作站认为我就是你。然后我就去邮件服务器取走你的邮件。我会联上你的文件服务器，移走你的文件，然后－－
Athena: 你能做得到吗？
Euripides: 当然！这些网络服务器怎么会知道我不是你?
Athena: 嗯，我不知道.我想我需要认真思考一下.
Euripides: 好吧。你想出来后告诉我.
第二幕
Euripides的办公室，第二天早上。Euripides坐在他的桌子旁边，读着他的邮件。Athena来敲门.
Athena: 我已经想出怎样保护一个开放的网络系统，使象你那样不道德的人不能用别人的名字使用网络服务。
Euripides: 真的吗？坐吧。
她坐下了。
Athena: 在我开始描述之前，我可以为我们的讨论先做一个约定吗？
Euripides: 什么约定？
Athena: 好，假设我这样说:&#8221;我想要我的邮件，于是我与邮件服务器联系，请求它把邮件送到我的工作站上来。&#8221;实际上我并没有联系服务器。我用一个程序来与服务器联 系并取得我的邮件，这个程序就是这个服务的客户端。 但我不想每次与服务器交互的时侯说:&#8221;客户端怎样怎样&#8221;.我只想说:&#8221;我怎样怎样,&#8221;记住，客户端在代表我做所有的事。这样可以吗？
Euripides: 当然。没问题.
Athena: 好。那么我要开始阐述我所解决的问题了。在一个开放的网络环境中，提供服务的机器必须能够识别请求服务的实体的身份。如果我去邮件服务器申请我的邮件，服务程序必须能够验证我就是我所申明的那个人。
Euripides: 没错.
Athena: 你可以用一个笨办法解决这个问题：服务器让你输入你的口令。通过输口令的办法我可以证明我是谁。
Euripides: 那确实很笨拙。在像那样的系统里面，每一个服务器必须知道你的口令。如果网络有一千个用户,那每个服务器就要知道一千个口令。如果你想改变口令，你就必须联系所有服务器，通知它们修改口令。我想你的系统不会那么笨。
Athena: 我的系统没那么笨。它是象这样工作的：不光人有口令，服务也有口令。每个用户知道他们自已的口令，每个服务也知道它自已的口令。有一个认证服务知道所有的口令，用户的和服务的。认证服务把口令保存在一个单独的中央数据库中。
Euripides: 这个认证服务有一个名字吗？
Athena: 我还没想好。你想一个吧？
Euripides: 把死人送过冥河的人是谁？
Athena: Charon?
Euripides: 对，就是他。如果他不能证实你的身份的话，他就不会把你送过河。
Athena: 你瞎编，是不是想重写希腊神话。Charon不关心你的身份，他只是确定你死了
没有。
Euripides: 你有更好的名字吗？
停了一下。
Athena: 没有，真的没有。
Euripides: 好，那我们就把这个认证服务“Charon”。
Athena: 好，我猜我该描述一下这个系统了吧，嗯?
比 如说我们想要一种服务：邮件。在我的系统里面你无法使用一种服务，除非Charon告诉服务你确实是你所申明的人。也就是说你必须得到Charon的认证 才能使用服务。当你向Charon请求认证的时候，你必须告诉Charon你要使用哪一个服务。如果你想用邮件，你要告诉Charon。 Charon请你证明你的身份。于是你送给它你的密码。Charon把你的密码和它数据库中的密码相比较。如果相等，Charon就认为你通过了验证。 Charon现在就要让邮件服务知道你通过了验证。既然Charon知道所有服务的密码，它也知道邮件服务的密码。Charon把邮件服务的密码给你，你 就可以使用这个密码使邮件服务相信你已通过验证。 问题是，Charon不能直接给你密码，因为你会知道它。下次你想要邮件服务的时候，你就会绕过Charon使用邮件服务而不需要认证。你也可以假装某人 来使用邮件服务。 所以不是直接给你邮件服务的密码，Charon给你一张邮件服务的“票”。这张票含有你的名字，并且名字是用邮件服务的密码加密的。 拿到票，你就可以向邮件服务请求你的邮件。你向邮件服务提出请求，并用你的票来证明你的身份。 [...]]]></description>
			<content:encoded><![CDATA[<p>Kerberos是一个重要的认证协议,它为互不相识的通信双方做安全的认证工作。Kerberos这个名字的原义是希腊神话中守卫冥王大门的长有三头的看门狗。下面这篇Kerberos的文章不知是哪位老大翻译的，感谢先！</p>
<p>这是MIT（Massachusetts Institute of Technology）为了帮助人们理解Kerberos的原理而写的一篇对话集。里面有两个虚构的人物：Athena和Euripides，通过 Athena不断的构思和Euripides不断的寻找其中的漏洞，使大家明白了Kerberos协议的原理。<br />
Athena: 雅典娜，智慧与技艺的女神。<br />
Euripides:欧里庇得斯, 希腊的悲剧诗人。<br />
译文如下：<br />
第一幕<br />
在一个小工作间里。Athena和Euripides正在相邻的终端上工作。<br />
Athena: 嗨，这个分时操作系统实在太慢了。我根本无法工作，因为每个人都登上去了。</p>
<p>Euripides: 不要对我报怨。我只是在这工作。<br />
Athena: 你知道我们需要什么吗？我们需要给每一个人一台工作，这样大家就不会担心计算机的速度了。并且，我们需要一个网络把所有的计算机都联起来。<br />
Euripides: 好。那么我们差不多要一千台工作站？<br />
Athena: 差不多吧。<br />
Euripides: 你知道一台普通的工作站的硬盘有多大吗？那里放不下所有的软件。<br />
Athena: 我已经有主意了。我们可以把系统软件放到服务器上。当你登录到工作站的时候，工作站会通过网络与其中一台服务器上的系统软件联系。这样的设置让一组工作站都使用同一份系统软件，并且利于系统软件的升級。只需改动服务器就可以了。<br />
Euripides: 好的。个人的文件怎到办呢？在分时操作系统上，我可以登录并从终端上取走我的文件。我能到工作站上取我的文件吗？我要象PC用户一样把我的文件放到磁盘上去吗？我希望不。<br />
Athena: 我想我们可以其它机器来存文件。你可以到任何一台机器上登录去取你的文件。<br />
Euripides: 打印怎么办呢？每个工作站都要有自已的打印机吗？谁来付钱？电子邮件呢？你怎么把邮件送到所有的工作站上去呢？<br />
Athena: 啊&#8230;..很明显我们没钱为每个人配一台打印机，但我们有专门的机器做打印服务。你把请求送到服务器，它就为你打印。邮件也可以这样做。专门有一台邮件服务器。你如果想要你的邮件，就联系邮件服务器，取走你的邮件。<br />
Euripides: 你的工作站系统听起来很不错。如果我有一台，你知道我要做什么吗？我要找出你的用户名，让我的工作站认为我就是你。然后我就去邮件服务器取走你的邮件。我会联上你的文件服务器，移走你的文件，然后－－<br />
Athena: 你能做得到吗？<br />
Euripides: 当然！这些网络服务器怎么会知道我不是你?<br />
Athena: 嗯，我不知道.我想我需要认真思考一下.<br />
Euripides: 好吧。你想出来后告诉我.<span id="more-60"></span><br />
第二幕<br />
Euripides的办公室，第二天早上。Euripides坐在他的桌子旁边，读着他的邮件。Athena来敲门.<br />
Athena: 我已经想出怎样保护一个开放的网络系统，使象你那样不道德的人不能用别人的名字使用网络服务。<br />
Euripides: 真的吗？坐吧。<br />
她坐下了。<br />
Athena: 在我开始描述之前，我可以为我们的讨论先做一个约定吗？<br />
Euripides: 什么约定？<br />
Athena: 好，假设我这样说:&#8221;我想要我的邮件，于是我与邮件服务器联系，请求它把邮件送到我的工作站上来。&#8221;实际上我并没有联系服务器。我用一个程序来与服务器联 系并取得我的邮件，这个程序就是这个服务的客户端。 但我不想每次与服务器交互的时侯说:&#8221;客户端怎样怎样&#8221;.我只想说:&#8221;我怎样怎样,&#8221;记住，客户端在代表我做所有的事。这样可以吗？<br />
Euripides: 当然。没问题.<br />
Athena: 好。那么我要开始阐述我所解决的问题了。在一个开放的网络环境中，提供服务的机器必须能够识别请求服务的实体的身份。如果我去邮件服务器申请我的邮件，服务程序必须能够验证我就是我所申明的那个人。<br />
Euripides: 没错.<br />
Athena: 你可以用一个笨办法解决这个问题：服务器让你输入你的口令。通过输口令的办法我可以证明我是谁。<br />
Euripides: 那确实很笨拙。在像那样的系统里面，每一个服务器必须知道你的口令。如果网络有一千个用户,那每个服务器就要知道一千个口令。如果你想改变口令，你就必须联系所有服务器，通知它们修改口令。我想你的系统不会那么笨。<br />
Athena: 我的系统没那么笨。它是象这样工作的：不光人有口令，服务也有口令。每个用户知道他们自已的口令，每个服务也知道它自已的口令。有一个认证服务知道所有的口令，用户的和服务的。认证服务把口令保存在一个单独的中央数据库中。<br />
Euripides: 这个认证服务有一个名字吗？<br />
Athena: 我还没想好。你想一个吧？<br />
Euripides: 把死人送过冥河的人是谁？<br />
Athena: Charon?<br />
Euripides: 对，就是他。如果他不能证实你的身份的话，他就不会把你送过河。<br />
Athena: 你瞎编，是不是想重写希腊神话。Charon不关心你的身份，他只是确定你死了<br />
没有。<br />
Euripides: 你有更好的名字吗？<br />
停了一下。<br />
Athena: 没有，真的没有。<br />
Euripides: 好，那我们就把这个认证服务“Charon”。<br />
Athena: 好，我猜我该描述一下这个系统了吧，嗯?<br />
比 如说我们想要一种服务：邮件。在我的系统里面你无法使用一种服务，除非Charon告诉服务你确实是你所申明的人。也就是说你必须得到Charon的认证 才能使用服务。当你向Charon请求认证的时候，你必须告诉Charon你要使用哪一个服务。如果你想用邮件，你要告诉Charon。 Charon请你证明你的身份。于是你送给它你的密码。Charon把你的密码和它数据库中的密码相比较。如果相等，Charon就认为你通过了验证。 Charon现在就要让邮件服务知道你通过了验证。既然Charon知道所有服务的密码，它也知道邮件服务的密码。Charon把邮件服务的密码给你，你 就可以使用这个密码使邮件服务相信你已通过验证。 问题是，Charon不能直接给你密码，因为你会知道它。下次你想要邮件服务的时候，你就会绕过Charon使用邮件服务而不需要认证。你也可以假装某人 来使用邮件服务。 所以不是直接给你邮件服务的密码，Charon给你一张邮件服务的“票”。这张票含有你的名字，并且名字是用邮件服务的密码加密的。 拿到票，你就可以向邮件服务请求你的邮件。你向邮件服务提出请求，并用你的票来证明你的身份。 服务用它自已的密码来把票解密，如果票能被正确的解密，服务器将票里的用户名取出。服务把这个名字和随票一起送上的用户名进行比较。如果相符，服务器就认 为你通过了验证，就把你的邮件发给你。<br />
你认为怎么样？<br />
Euripides: 我有些问题。<br />
Athena: 我猜到了。请讲。<br />
Euripides: 当服务解密一张票的时候，它如何知道它是被正确的解密的？<br />
Athena: 我不知道。<br />
Euripides: 也许你应该在票里包含有服务的名字。这样当服务解密票的时候，它就可以通过能否在票中找到自已的名字来判断解密是否正确。<br />
Athena: 很好。那票就应该是这个样子：<br />
(她把下面的东西写在了一张纸上)<br />
票-{用户名：服务名}<br />
Euripides: 那票就只包含用户名和服务名？<br />
Athena: 用服务的口令加密。<br />
Euripides: 我不认为这些信息就可以让票安全。<br />
Athena: 什么意思？<br />
Euripides: 假设你向Charon请求一张邮件服务的票。Charon准备了一张有你名字“tina”<br />
的 票。假设在当票从Charon传给你的过程中我拷了一份。假设我让我的工作站相信我的用户名是”tina“。邮件客户程序认为我就是你。用你的名字邮件客 户程序用偷来的票向邮件服务器提出请求。邮件服务器把票解密，认为它是合法的。票里的用户名和发送该票的用户名是匹配的。邮件服务器就会发给 我你的邮件。<br />
Athena: 喔!那可不太好。<br />
Euripides: 但是我想到了一个办法来解决这个问题。或者说部分解决。我想Charon应该在票中包含更多的信息。除了用户名，票还应包含请求票的用户的IP地址。这将 给你增加一层安全性。 我来演示。假设现在我偷了你的票。这票有你工作站的IP地址，并且这地址配不上我的<br />
工作站的地址。用你的名字我把偷来的票送给邮件服务器。服务程序把用户名和网络地址从票中解出，并试图匹配用户名和网络地址。用户名匹配可网络地址不匹配。服务器拒绝了这张票，因为它明显是偷来的。<br />
Athena: 英雄，英雄!我怎么会没想到。<br />
Euripides: 好了，这就是我要表述的。<br />
Athena: 那么票应该是这个样子的。<br />
她把下面的东西写在了黑板上。<br />
票-{用户名：地址：服务名}<br />
Athena: 现在我真的很激动。让我们来建一个Charon系统看看它是否工作!<br />
Euripides: 没那么快。对于你的系统我还有些问题。<br />
Athena: 好吧。(Athena从她的椅子上探出了身子)快说。<br />
Euripides: 听起来好像每次我想要得到服务我都要去取一张新票。如果我整天的工作，我可能不只一次的要取我的邮件。我每次取邮件都要去取一张新票吗？如果真是这样，我不喜欢你的系统。<br />
Athena: 啊。。。我不明白为什么票不能被重用。如果我已经得到了一张邮件服务的票，我可以一次又一次使用它。当邮件客户程序用你的名字请求了服务，它就传了一份票的拷贝给服务。<br />
Euripides: 好一些。但我仍有问题。你似乎暗示我每次使用还没有票的服务时，我都必须给Charon我的密码我登录后想取我的文件。我向Charon请求我的票，这意 味着我不得不使用我的密码。然后我想读我的邮件。又向Charon发一次请求，我又要输一次我的密码。现在假设我想把我的邮件送去打印。我又要向 Charon发一次请求。你知道了吧？<br />
Athena: 啊，是的，我明白了。<br />
Euripides: 并且如果这还不够糟的话，想想看：它好像是这样，当每次你要向Charon认证的时候，你就要用明文在网络上传输你的口令。像你这样的聪明人可以监视网络并且得到别人的口令。如果我得到你的口令，我就可以用你的名字来使用任何服务。<br />
Athena叹了口气。<br />
Athena: 确实有严重的问题。我想我该回设计室去了。<br />
第三幕<br />
第二天一早，Athena在咖啡间遇上了Euripides。在Euripides倒咖啡的时候，Athena拍了<br />
拍Euripides.<br />
Athena: 我有了一个新的Charon的版本来解决我们的问题。<br />
Euripides: 真的吗？好快呀。<br />
Athena: 好，你看，这些问题困扰了我一夜。<br />
Euripides: 一定是你良心发现了。我们去那边的小会议室吧？<br />
Athena: 好的。<br />
两人去了小会议室。<br />
Athena: 我要重新描述问题，但我要根据我们的需要进行适当的转换。<br />
Athena清了清嗓子。<br />
Athena: 第一个限制：用户只输一次口令，在他们工作站启动的时候，这意味着当你需要申请新的服务的票时，不需输入你的口令。第二个限制：口令不能在网络上进行明文传输。<br />
Euripides: 好的。<br />
Athena: 我以第一项限制开始：你只需要输入你的口令一次。我创造了一个新的网络服务来解决这个问题。 它叫做“票据授权”服务，这个服务把Charon的票给用户。使用它必须要有票：票据授权的票。 票据授权服务其实只是Charon的一个版本，它可以存取Charon的数据库。它是Charon的一部分，可以让你通过票而不是口令来进行认证。 总之，认证系统现在是象这样工作的：你登录到一个工作站，用一个叫kinit的程序与Charon 服务器通讯。你向Charon证明你的身份，kinit程序取得一张票据授权票。 现在你想从邮件服务器上取你的邮件。你还没有邮件服务器的票，所以你用“票据授权”票去取邮件服务的票。你不需要使用口令去取新的服务票。<br />
Euripides: 每次我想要另一种网络服务的时候，我都要去取一张“票据授权”票吗？<br />
Athena: 不。记住，上次我们已经同意票是能被重用的。一旦你要用到票据授权票，直接用就可以了。<br />
Euripides: 好，有道理。既然你能重用票，一旦你得到了某个服务的票，你就无需再去取了。<br />
Athena: 对啊，那不好吗？<br />
Euripides: 好的，我没话说，只要你在取得票据授权票的时候没有用明文在网上传输你的口令。<br />
Athena: 如我所说，我已解决了这个问题。听起来好像是，当我说我要和Charon联系取<br />
得票据授权票的时候，你就要在网络上传输明文密码。但其实不是这样的。 实际上是，当你用kinit程序取得票据授权票的时候，kinit没有把你的口令送<br />
给Charon服务器，kinit只送你的用户名。<br />
Euripides: 很好。<br />
Athena: Charon用用户名去查找你的口令。然后Charon就会组一个包含票据授权票的包。在送给你之前，Charon用你的口令去把这个包加密。 你的工作站收到了包。你输入你的口令。kinit用你的口令对这个包进行解密。如果成功你就向Charon成功的进行了认证。你现在有了票据授权票，你可 以用这张票来取得其它的票。<br />
这些奇思妙想怎么样？<br />
Euripides: 我不知道&#8230;我正在思考。你知道你的系统一部分工作得很好。你的系统只需要我认证一次。以后，Charon会给我服务的票而我需要关心。天衣无缝，天衣 无缝。但服务票的设计还是有一些困扰我。服务票是可重用的。我同意它们应该能被重用，但重用的服务票，由于它们自身的性质，是非常危险的。<br />
Athena: 什么意思？<br />
Euripides: 这样看。假设你正在用一个不安全的工作站。在你登入后，你需要邮件服务票，打印票，和文件服务票。假设你无意中在你退出后留下了那些票。 现在假设我登录到那个工作站并且发现了那些票。我想制造一些麻烦，于是我就用你的名字登录了。既然那些票上是你的名字，那我就可以取你的邮件，打大量的文 件。这些完全是因为这些票被偶然的放在了那里。 并且我还可以把这些票拷走，永远的使用它们。<br />
Athena: 但是这很好解决。我们可以写一个程序，在用户退出的时候把票销毁掉，这些<br />
票也主不能再用了。<br />
Euripides: 那么很明显你的统应该有一个票据销毁程序，让用户依赖这样的机制是非常愚蠢的。你不能指望用户在他们退出的时候会销毁票据。并且甚至不能依赖销毁票据本 身，看下面的情况。 我有一个程序可以监视网络并且拷内别人的服务票据。假设我想牺牲你。我等你登到工作站的时候，打开我的程序并拷贝一份你的票。 我等你退出并离开。我把我的工作站的地址调整为你登录时用的地址。我让工作站认为我是你。我有你的票，你的用户名，你的地址。我可以用这些票来使用你的服 务。<br />
你离开工作站时销毁你的票已没并系。这些我偷来的票可以一直使用下去，因为你现在的票并没有可以使用多少次的期限，或可以使用多长的时间。<br />
Athena: 哦，我明白你所说的了！票不能是永远合法的，因为它可能是一个非常大的安全隐患。我们应该限制每一张票可以用多长的时间，也许可以给每张票设一个有效期。<br />
Euripides: 非常正确。我想票需要增加两项信息：生存期表示票多长时间内是合法的，和一个时间标记来说明Charon是什么时候发出这张票的。<br />
Euripides走到了黑板写下了如下的内容：<br />
票｛用户名：地址：服务名：有效期：时间戳｝<br />
Euripides: 现在当服务解开票时，它检查票的用户名，地址是否与发送者匹配，然后它<br />
用有效期和时间戳来检查票是否有效。<br />
Athena: 很好。典型的票使用哪长的有效期呢？<br />
Euripides: 我不知道。也许是一个典型工作站的工作周期。就八小时吧。<br />
Athena: 那如果我在工作站呆的时间超过八小时，所有的票将会失效。包括票据授权票。那我就要重新向Charon作认证，在八小时以后。<br />
Euripides: 是不是不合理？<br />
Athena: 我想不是。好我们就定下来吧－－票在八小时后失效。现在我有一个问题问你。假设我从网络上拷了　你的票－－。<br />
Euripides: (眨了眨眼睛）啊，Tina!你不会真的这样做吧？<br />
Athena: 这只是为了讨论。我拷了你的票。现在我等你退出并离开。假设你有一个医生的约会或聚会要参加，你在两个小时后退出，并且你在退出之前销毁了你的票。<br />
但我已经偷了你的票，它们还可以使用六小时。这给了我足够的时间用你的名义去取你的文件并打印一千份什么东西。 你看，时间戳工作的很好如果小偷选择在它失效以后来用的话。如果小偷能在它失效之前用&#8230;。<br />
啊，好&#8230;当然，你是对的。<br />
Athena: 我想我们遇上了一个大问题了。(她叹了口气)<br />
停了一下。<br />
Euripides: 我想这意味着你今晚要忙了。再来点咖啡？<br />
Athena: 为什么不。<br />
第四幕<br />
第二天早上在Euripides的办公室。Athena来敲门。<br />
Euripides: 你今早有黑眼圈了。<br />
Athena: 好了，你知道的。又是一个漫漫长夜。<br />
Euripides: 你解决了重演的问题了吗？<br />
Athena: 我想是的。<br />
Euripides: 请坐。<br />
她坐下了。<br />
Athena: 照旧，我重申一下问题。票是可重用的，在一个限定的时间内（八小时）。如果谁偷了你的票并在它失效之前使用，我们毫无办法。<br />
Euripides: 确实如此。<br />
Athena: 我们可以把这个问题理解为设计一种别人无法重用的票。<br />
Euripides: 但这样的话你每次用新服务时都要取一张新票。<br />
Athena: 对。但那是很笨的解决办法。（稍顿。）啊，我怎样继续我的讨论呢？（她沉思了一会儿）。<br />
好 的，我要重述一个问题，看有什么必须条件。网络服务必须能够证明使用票的人就是票上所申明的人。 我来顺着认证的过程再走一遍，这样我就可以演示我的解决方案。 我现在想用一个网络服务。我通过启动工作站上的客户端来使用它。客户端送三样东西给服务器：我的名字，我的工作站的网络地址，适当的服务票据。 这张票包含了申请这张票的人的名字和他（她）申请时所使用的工作站的地址。它也包含了票的有效期和时间戳。所有这些信息都被服务的密码加密了。<br />
我们现在的认证模式基于以下的测试：<br />
服务能对票解密吗？<br />
票在有效期以内吗？<br />
票中的名字和地址与申请者的名字和地址匹配吗？<br />
这些测试证明了什么？<br />
第一个测试证明了票是不是来自Charon.如果票不能被适当的解密，说明票不是来自真正<br />
的Charon.<br />
真正的Charon会用服务的票来加密票。Charon和服务是唯一知道服务密码的两个实体。<br />
如果票被成功的解密，服务知道它来自于真的Charon.这个测试防止了有人伪造假票。<br />
第二项测试检查票是否在有效期以内。如果过期，服务拒绝。这项测试阻止使用旧票，<br />
因为票可能是偷来的。<br />
第三项测试检查票的用户名和地址是否匹配请求者的用户名和地址。如果测试失败，说<br />
明使用者使用了别人的票。这张票当然被拒绝。<br />
如果名字和地址匹配，这个测试证明了什么？什么也没有。票可以被偷走，用户名和网<br />
络地址都可以被改变，如果需要的话。正如我昨天指出的那样，票可以在有效期内被盗用。<br />
因为服务不能确定票的发送者是不是合法用户。<br />
服务之所以无法判断是因为它没有与用户共享一个秘密。这样看。假如我正在埃尔斯诺<br />
尔（哈姆雷特中的城堡）值勤，你打算来和我换班。但除非你说出正确的口令，否则我不<br />
会与你换班的。我们共享了一个秘密。它可能是某人为所有值勤的人所设的。<br />
于是昨晚我就在想，为什么Charon不能为合法用户与服务之间设一个口令呢？Charon发<br />
一份口令给服务，同时发一份给用户。当服务从用户那里收到一张票，它可以用这个口令<br />
检验用户的合法性。<br />
Euripides: 等一下。Charon如何同时发两份口令？<br />
Athena: 票据的拥用者从Charon的回应中得到口令，像这个样子：<br />
她在黑板上写下了：<br />
Charon的回应－[口令｜票]<br />
服务从票中获取口令。票的格式如下：<br />
票－｛口令：用户名：地址：服务名：有效期：时间戳｝<br />
当你要请求服务时，客户端程序生成一个‘验证器’。验证器包含了你的名字和你工作站的地址。客户端用口令把这些信息加密，口令是你请求票据时得到的。<br />
验证器－｛用户名：地址｝用口令加密。<br />
生成验证器以后，客户端把它和票一起送给服务。因为服务没有口令，所以它不能解密<br />
验证器。口令在票中，于是服务先解开票。<br />
解开票以后，服务得到以下的东西：<br />
票的有效期和时间戳；<br />
票的拥有者的名字；<br />
票拥有者的网络地址。<br />
口令。<br />
服务检查票是否过期。如果一切正常，服务就用口令去解验证器。如果解密没有问题，服务将会得到一个用户名和网络地址。服务用它们去和票里的用户名和网络地址去匹配，如果正确，那么服务认为票的发送者确实是票的真实拥有者。<br />
Athena暂停了一下，清了清喉咙，喝了点咖啡。<br />
我认为口令验证器的机制解决了盗用的问题。<br />
Euripides: 也许。但我想。。。攻击这个系统我必须有验证器。<br />
Athena: 不。你必须同时拥有验证器和票。没有票，验证器是没有用的。解开验证器必须要有口令，服务必须解开票才会有口令。<br />
Euripides: 好，我明白了，你是说当客户程序联系服务时，它同时送上票和验证器？<br />
Athena: 是的，我就是这个意思。<br />
Euripides: 如是真是这样，什么可以阻止我把票和验证器都偷走呢？我可以写一个程序，如果我拥有了票和验证器，我就可以一直使用它至有效期结束。我只需改变我的用户名和工作站的地址。不是吗？<br />
Athena: (咬了咬她的嘴唇）是的。多沮丧啊。<br />
Euripides: 等等，等等，等等！这不难解决。票在有效期内是可重用的，但那并不意味着验证器是可重用的。假设我们设计了验证器只可以被用一次。这可以吗？<br />
Athena: 好，也许。我样来想一下，客户端程序生成验证器，然后把它和票一起送给服务。真的票和验证器比你拷贝的要先到。如果验证器只能被用一次，你的拷贝就失效了。 啊，这就对了。我样现在需要做的就是发明一和方法使得验证器只能被用一次。<br />
Euripides: 没问题。我们把有效期和时间戳放在上面。假设每个验证有两分钟的有效期。当你想用一个服务时客户端生成验证器，标上当前的时间，把它和票一起送给服务。 服务器收到了票和验证器，服务器解开验证器，它检查验证器的时间戳和有效期。如果验证器还没失效，所有其它的检查都通过了，那么服务器就认为你通过了认 证。 假设我通过网络拷贝了一份验证器和票，我必须改变我的工作站的网络地址和我的用户名，这差不多要用几分钟。那是非常苛刻的要求，我不认为是可能的，除 非。。。 嗯，有一个潜在的问题。假设不是在网络的转输中拷贝到票和验证器，我拷贝了一份原始的从Charon而来的包，这个包是你向Charon请求时的回应。 这个包，有两个口令在里面：一个是你的，一个是服务的。服务的口令隐藏在票中，我取不到，但另一个呢？那个你用来生成验证器的？ 如果我得到了口令，我就用它来建自已的验证器，如果我能建自已的验证器，我就能攻破你的系统。<br />
Athena: 这就是我昨晚所想的，但是当我顺着票的处理过程一想，发现那样偷走验证器是不可能的。<br />
你 在一台工作站坐下，用kinit程序得到你的票据授权票。kinit要求输入用户名，你输入以后，kinit把它送给Charon.Charon用你的名 字查找你的口令，然后生成一张票据授权票。作为处理的一部分，Charon生成了一个你与票据授权服务共享的口令。Charon把口令和票据授权票一起送 给你，并且在发关之前用你的口令将它加密。<br />
Charon送出了包。某人取得了这个包，但他们无能为力因为它是用你的口令加过密的。特别是，无 人可以偷走票据授权服务的口令。 kinit收到了票据包并要求你输入你的口令。如果你输入正确的口令，kinit解开包取出了口令。 现在你注意kinit的处理，你去取你的邮件。你打开邮件客户端。这个程序查找一张邮件服务的票但没有找到（你还没取过你的邮件）。客户端用票据授权票去 申请一张邮件服务的票。 客户端为票据授权的过程生成了一个验证器，并用票据授权的口令把验证器加密。客户端把验证器送给了Charon，票据授权票，你的名字，你的工作站的地 址，邮件服务的名字。票据授权服务收到了这些东西，并通过了认证检查。如果一切都通过，票据授权服务将会得到那个与你共享的口令。现在票据授权服务为你生 成了一张邮件服务的票，在这个过程中生成了一个你与邮件服务共享的口令。票据授权服务把这些东西打成包送给你的工作站。包里有票和口令。在送包之前，票据 授权服务用票据授权的口令把包加密。做完以后，包被送出去。 这样邮件服务票的包通过网络被送了出来。假设网络上的某人将它复制了一份。他不幸的发现包是用票据认证的口令加过密的。既然无法解密，他就不能得到邮件口 令。没有口令，他就不能使用任何在网络上传送的邮件服务的票。 现在我觉得我们是安全的。你认为呢？<br />
Euripides: 也许吧。<br />
Athena: 也许！你就只会说这个吗！<br />
Euripides: (大笑）别在意。你现在应该知道我处理问题的方式了。我猜我和你昨晚都工<br />
作到了半夜。<br />
Athena: 哼！<br />
Euripides: 好的，大半夜。实际上，这个系统似乎是完全可行的。口令的方案解决了我<br />
昨晚想到的一个问题：相互验证的问题。<br />
稍顿。<br />
我说一下好吗？<br />
Athena: (有点冷淡）请便。<br />
Euripides: 你真好。(Euripides清了清自已的嗓子）昨晚，当口令和验证器在我脑子里转的时候，我想去找出这个系统新的问题，我想我发现了一个很严重的问题。我下面就演示一下。<br />
假 设你厌倦了现在的工作，决定换一个。你想用公司的激光打印机打印求职信，把它们送给猎头和其它的雇主。于是你输入打印命令，命令去取得服务票，然后把票送 到打印机。这是你认为它应该被送到的地方。实际上你并不知道你的请求被送到了正确的打印服务器。 假设一些无耻的人－－比如说你的老板－－调整了系统，把你的请求送到了他办公室的打印机。他的打印服务不关心票的内容。它告诉你的工作站服务已准备好打印 你的文件。打印命令被送到了假的打印服务器，你有麻烦了。 我从相反的方向表达了相同的问题。用口令和验证器，Charon能够保护的它的服务器防止错误的用户使用，但它不能保护它的用户使用错误的服务器。系统需 要为客户端程序提供一种验证服务器的方法，在它向服务器发送敏感信息之前。系统必须允许交互验证。 但口令的方案解决了这个问题。让我们回到打印服务器的场景。我想要打印客户程序确<br />
认它送交的服务是合法的服务。 这就是程序要做的。我输入打印命令并给出一个文件名。这时我已经有了打印服务票和口令。客户程序用密码生成了一个验证器，然后把验证器和票送给了假设的打 印服务器。客户端这时还没有送打印文件，它在等待从服务的返回。 真的服务收到票和验证器，把票解密并得到口令，然后用口令解开验证器。这样服务端做完了所有的认证。 测试已经确认了我的身份。现在服务程序要准备一个响应包来证实它自已的身份。它用口令加密了返回包，并把包送给了等待的客户端。 客户端收到了包并试图用口令把它解开。如果包被正确的解开得到了正确的服务器响应信息，客户端程序就知道了这个服务器是合法的服务器。然后这时客户端向它 发出打印命令。 假设我的老板改变了一下系统使得他的打印机看起来好像是我想要用的那个。我的客户端送了票和验证器给它并等待它的响应。假冒的打印服务无法生成正确的响应 因为它无法把票解开并得到口令。这样的话客户端就不会送打印命令给它因为客户端没有得到正确的<br />
响应。最后客户端放弃等待并退出。我的打印没有完成，但至少我的求职信不会放在我的<br />
对头的桌子上。<br />
好啊，我想我们有了Charon认证系统的坚实的基础。<br />
Athena: 也许。不管怎么说，我不喜欢Charon这个名字。<br />
Euripides: 你不喜欢吗？什么时候？<br />
Athena: 我从来都不喜欢，因为它的名字听起来没意义。有一天我和我荷迪斯（冥王)叔<br />
叔<br />
谈到了这个，他推荐了另一个名字：冥王的三个头的看门狗。<br />
Euripides: 啊，你是说“Cerberus&#8221;.<br />
Athena: 你说什么语言啊！&#8221;Cerberus&#8221;实际上是。。。<br />
Euripides: 哦，不叫这个吗？<br />
Athena: 当然，谁让你是罗马人！而我是希腊人，它是一条希腊的看门狗，它的名字是<br />
”<br />
Kerberos“，”Kerberos“是‘K’打头的。<br />
Euripides: 好吧，好吧，别发火。我同意这个名字。实际上，它有一个好的脖环。再见<br />
吧，Charon,欢迎你，Kerberos.<br />
后记<br />
这 篇对话是于1988年写的，是为了帮助读者理解Kerberos V4的运行方式。经过了这么多年，它仍然非常好的服务于此。当我把这篇文章转换成HTML的时候，我惊讶的发现这个文档对Kerberos　V5仍然非常 有用。虽然很多东西改变了，但核心概念并没有变。实际上，Kerberos V5对Kerberos只做了两处改变。<br />
第一处改变是因为意识到 验证器用少于五分钟的有效期不足以防止攻击者进行重演，如果攻击者是用一个程序自动的截取票和验证器并进行重演的话。 在Kerberos V5中，验证器真正的只能用一次因为服务器用‘重演缓冲区’保存了最近一次提交的验证器的信息。如果攻击者试图截取验证器并重用它，‘重演缓冲区’会发现 验证器已经被提交了。<br />
第二个主要改变是Kerberos送给kinit服务票的时候，票不再是用用户的口令加密。它已经用票据授权服务的口令 加过密了。票据授权服务的票被用来获取其它票的时候，它直接就被传输了。因此票不需要再用用户的口令加密一次。（服务器响应的其它部分，如口令，仍然是用 用户的口令加密的。） 一个类似的改变也应用到票据授权服务协议；从票据授权服务返回的票也不再用票据授<br />
权服务的口令来加密了，因为它所包含的票已经被对应的服务的口令加过密了。举例来说<br />
，<br />
Kerberos V4的包像这样：<br />
KDC_REPLY = {TICKET, client, server, K_session}K_user<br />
意思是：｛｝中的内容是用K_user来加密的。<br />
TICKET = {client, server, start_time, lifetime, K_session}K_server<br />
在Kerberos V5中，KDC_REPLY现在看起来像这样：<br />
KDC_REPLY = TICKET, {client, server, K_session}K_user<br />
(注意：票已经不再用K_user来加密了)<br />
当然，Kerberos V5中还有许多新特性。用户可以在另一个网络中安全的提交他们的票；并且，用户可以把他们的一部分认证权转给服务器，这样服务器就可以作为用户的代理。其它的新特性包括：用更好的加密算法替换了DES加密算法，如三重DES加密。读者如果对V<br />
4<br />
与V5的变化感兴趣的话，可以读一下&#8221;The Evolution of<br />
the Kerberos Authentication System&#8221;,作者是Cliff Neumann和Theodore Tso. 我希望你能对这篇介绍Kerberos协议的文章感兴趣。我祝愿你在未来的探索中更进一步</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/design/kerberos-basic/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
