<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Sung in Blog-文章分类-software Development</title><link>http://www.blogjava.net/qq13367612/category/3973.html</link><description>&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font class="subhead" size=3&gt;&lt;b&gt;一些技术文章 &amp; 一些生活杂碎&lt;/b&gt;&lt;/font&gt;</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 09:14:49 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 09:14:49 GMT</pubDate><ttl>60</ttl><item><title>windows环境CVS client使用入门</title><link>http://www.blogjava.net/qq13367612/articles/17125.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Fri, 28 Oct 2005 00:48:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17125.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17125.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17125.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17125.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17125.html</trackback:ping><description><![CDATA[<STRONG>CVS client使用前必须明白的基本概念<BR><EM>1,CVS</EM></STRONG><BR>CVS (Cuncurrent Versions System)是基于TCP/IP协议的版本控制工具,也是Open source界最重要的开发工具之一。 <BR>它原来主要工作在UNIX平台下，现在在windows平台上也出现了很多GUI工具。 <BR>关于其由来，发展，请参阅http://www.redsaga.com/CVS_newbie_win32/www.cvshome.org 。 <BR>CVS和其他大部分版本控制软件一样，是Client/Server结构的。你必须在本地为CVS repository准备好一个目录，来和服务器同步源代码。 <BR>和在Windows 开发平台中拥有很大用户群的Visual Source Safe(VSS)相比,CVS主要由两个不同之处。 <BR>一是VSS依靠服务器上的一个共享目录提供服务，每一个client必须能够访问这个共享目录。这也就决定了source safe在TCP/IP环境下使用很困难。对于分布跨越数个城市甚至国家的工作小组来说，只有通过VPN才能够安全的访问source safe数据库。(SourceGear公司(www.sourcegear.com)发售名为SourceOffSite的商业软件包,US$239 per user，也可以为远程用户提供通过TCP/IP访问source safe数据的能力。) 而CVS依靠TCP/IP连接提供服务，所以它天生就是为了在internet上协同工作而设计的。虽然基本的pserver连接安全性不是很高，但是通过使用SSH,可以获得很高的安全性。 <BR>二是CVS反对对文件上锁的机制。VSS以及其他很多传统版本控制工具要求一个文件只能有一个使用者，它必须先checkout声明编辑文件的独享权力，直到checkin为止。但是对于地理上不限制使用者位置的CVS来说，等待一个用户checkin是一件痛苦的事情，而互相沟通比一个紧密工作的团体更困难。CVS采取多个用户可以同时对一个文件进行编辑，然后commit的方式解决这个问题。假设由于沟通不足出现冲突，使用者必须手工解决冲突之后再进行commit。在这种情况下，冲突的开发者必须努力进行足够的沟通以避免再次冲突。 <BR>CVS服务器可以被配置为把commit记录自动张贴到新闻组或者开发者的email信箱中去。注意这些辅助记录将有助于开发者之间的合作。 <BR><STRONG><EM>2, repository,module</EM></STRONG><BR>CVS服务器上，一个源代码仓库被称为一个repository,一个server上通常可以运行多个repository,每个repository都是完全独立的，可以有不同的用户列表和访问规则。在一个repository之下，文件按照module组织，每一个module就相当于一个工程,大致上相当于Source safe里面的project。 <BR>VSS在你连接上服务器之后，会列出所有的project。但并不是所有的CVS server都会提供module的列表。事实上，哪些module被公开是由管理员控制的。如果你知道一个被隐藏的module的名字，你仍然可以正常的访问这个module。 <BR><STRONG><EM>3,CVSROOT</EM></STRONG><BR>CVS依靠运行在服务器上的一个服务程序提供TCP/IP的连接。为了访问一个CVS数据库，你必须知道你所使用的协议，服务器的地址，服务器提供的Repository的名称以及你的用户名和密码。 <BR>有数种协议可供选择。Unix/Linux机器上的CVS通常使用pserver协议，这是一种不非常安全的协议，但是如果你有额外的安全要求，可以通过SSH进行增强。除此之外，NT机器还支持ntserver协议，它通过主机的NT用户表进行访问控制(但是这是在internet上不可用的方法）。kserver和gserver协议用的比较少，他们依据Kerboses提供额外的安全保护。 <BR>你有必要知道CVSROOT这个参数。CVSROOT是一个用":"开始及分隔各个部分的字符串，它包含了协议、用户名、服务器地址和repository名称。对于用户来说，CVSROOT就像URL一样，是访问一个server的途径。 <BR>一个典型的CVSROOT=:perser:cao@61.155.107.187:/cvs。这里,pserver是协议名称，cao是用户id，61.155.107.187是主机ip,/cvs是repository的名字。NT主机的repository一般会采取d:/CVSROOT之类的格式。 <BR>另一个例子是:pserver:anonymous@jivesoftware.com:/cvs,这是jivesoftware公司提供的开放源代码java技术论坛的CVSROOT。 <BR>在windows下使用命令行方式，这个参数可以通过一个环境变量使用。在windows 2000/XP系统中，你可以通过在'My computer'的properties中选择advanced,然后选择'Enviroment Variables'来输入这个环境变量。 <BR><STRONG><EM>4，checkout,update</EM></STRONG><BR>为了得到module下面的源代码，你只需要使用checkout指令。和Visual source safe不一样，checkout只是取得文件，而非锁文件。 <BR>如果你已经有了本地文件，为了和server保持同步，你需要进行update操作。update会自动把server上的新内容取到本机来，如果你本地文件进行过了改动，它会帮您做合并工作。 <BR>checkout 和 update既可以针对一个特定的文件，也可以针对一个目录或者整个module。 <BR><STRONG><EM>5, commit</EM></STRONG><BR>如果你对本地代码做了任何修改，或者增加一个文件，删除一个文件，每当你需要把你的改变提交到server上的时候，你就需要做commit动作。假设两个人都在本地修改了同一个文件，那么他们就像在进行一个竞赛，如果你快，那么你赢了。后commit的人将被server拒绝，不得不合并你的修改再次提交。 <BR>commit既可以针对一个特定的文件，也可以针对一个目录或者整个module。 <BR><STRONG><EM>6, revision</EM></STRONG><BR>Revision是指每一个文件的版本信息。当你第一次增加一个文件到repository的时候，它会有一个初始revision是1.1,以后每次提交，就会增加到1.2,1.3... <BR>在一个branch中的文件，有相对于这个branch的版本号。如果你对文件作了tag,那么你会看到revision变成1.1.1.1的形式。具体的含义我们在branch和tag的时候描述。 <BR><STRONG><EM>7，branch</EM></STRONG><BR>Branch是一棵正常生长的代码树中的枝杈。开始的时候，任何一个module都有一个主枝被称为'HEAD'。 <BR>一个branch最终要么被合并到主干中去，要么被结束。branch通常用来debug,如果这个bug被fix了，修改bug的代码应该被合并到主枝上去。一个branch也可能经历多次与主枝的合并。 <BR><STRONG><EM>8, tag</EM></STRONG><BR>Tag用来进行标示必要的信息。当您进行一次公开发布之前，您有必要对主枝标示"release 1.0"。这样您以后就可以随时回到这个版本。 <BR>//to do: 请完善这里的描述<BR><BR><STRONG>CVS命令行</STRONG><BR>在得到CVSROOT和你的口令之后，你就可以试着登陆了。 <BR>首先，由于其他所有的GUI工具都是基于CVS基本协议的，而且他们可能会提供CVS的命令行或者等价形式作为显示的一部分，所以你应该对命令行操作有所了解。如果你还没有一个cvs。exe的命令行程序，从http://www.redsaga.com/CVS_newbie_win32/www.cvsnt.org你可以得到一个cvsnt的下载连接，其中就包含了一个命令行的cvs.exe程序。我们先从它开始（为了作为一个client使用，你不需要安装cvsnt的server组件)。CVSNT的cvs.exe是专门为windows编写的，你需要把cvs.exe放在你的path里面。 <BR><STRONG><EM>1.进入命令行方式。</EM></STRONG><BR>和VSS一样，你也需要在本地有一个工作目录对应于一个repository。假设这个目录是'd:\works\sandbox'。请切换到这个目录。<BR>输入"cvs"。你会看到: <BR><IMG height=252 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-1.jpg" width=642> <BR>这些提示信息告诉您关于cvs的基本语法。cvs后面跟着的是全局参数，然后是命令，最后是命令的参数。<BR><EM><STRONG>2.login </STRONG></EM><BR>正确的login不会有任何输出，否则会告诉你错误原因。<BR>cvs <BR><IMG height=47 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-2.jpg" width=640> <BR><EM><STRONG>3.下面我们看看这个CVS server中有哪些module。 </STRONG></EM><BR><IMG height=75 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-3.jpg" width=640> <BR><STRONG><EM>4.假设现在我们工作的项目是projectX,下面我们需要得到它下面的全部文件。<BR></EM></STRONG><IMG height=179 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-4.jpg" width=641><BR>现在让我们看一下我们得到了什么。 <STRONG><EM><IMG height=232 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-5.jpg" width=643></EM></STRONG><BR>在d:/works/sandbox目录下，你可以看到有一个projectX目录。这就是你得到的所有文件。 <BR>这个目录下你会发现一个叫做 CVS的目录。危险！请不要删除这个目录，或者改名，或者改动其中的任何文件，除非你知道你在做什么。这个目录是CVS的控制目录。如果你用过source safe,你一定很熟悉。scc这个文件，CVS目录的作用就和这个控制文件一样，都是用来记录你访问服务器的参数。 <BR>这里我们需要解释一下cvs和VSS的名词差别。在VSS中，checkout意味着你将获得一个文件的修改权，而cvs中checkout的这个含义取消了，仅仅指取得文件的新版本。很多cvs server会有一个anonymous用户，他只有checkout权限，也就意味着它只读。 <BR><BR><EM><STRONG>5.让我们试着加入一个文件:</STRONG></EM><IMG height=90 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-6.jpg" width=640><BR>在d:/works/sandbox/projectX下，新建一个文件newfile.txt, <BR>然后，在这个目录下执行: <BR><IMG height=62 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-7.jpg" width=640><BR>你需要commit它才能被sever接受。<BR><IMG height=20 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-8.jpg" width=638> <BR>一个notepad窗口弹出请您输入注释。 <BR><IMG height=276 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-9.jpg" width=641> <BR>这是commit完成的结果。现在的版本号是1.1。<BR><IMG height=114 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-10.jpg" width=640> <BR><STRONG><EM>6.好了，现在假设您需要改一下这个文件的内容。<BR><IMG height=93 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-11.jpg" width=639> </EM></STRONG><BR>CVS可以帮助您比较现在您的版本和repository中的版本有什么不同。<BR><IMG height=193 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-12.jpg" width=638> <BR>好了，现在您可以提交您的新文件。 <BR><IMG height=100 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-13.jpg" width=635> <BR>CVS会帮您保留您的各个版本。在commit之后，现在我们来看一看各个版本的history。 <BR><IMG height=340 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-14.jpg" width=630> <BR><STRONG><EM>7.最后，为了完成这个试验，请把这个newfile文件删去。 </EM></STRONG><BR><IMG height=185 src="http://51cmm.csai.cn/casepanel/CM/Images/No063-15.jpg" width=636><BR>我们现在认识了一些最基本的CVS入门级指令。 <BR>其实CVS是非常强大的，我们并没有用到一些更复杂的功能，请参阅cvs的手册来得到更为详尽的帮助。 <BR>在多人同时开发的时候，冲突有时候也是不能避免的。 <BR>// to do:加入处理 cvs update和处理merge的部分。 <BR>更多的资料请参阅Karl Fogel的《Open Source Development With CVS》一书。该书的中文译本《CVS开源软件开发技术》由机械工业出版社出版(ISBN 7-111-08891-3/TP.1885,人民币35.00)。按此连接到华储网上电脑书店订购http://www.huachu.com.cn/asp/book/brow.asp?lbbh=B99112091 <BR><STRONG>用MFC编写的windows平台CVS图形界面 --- WinCVS(未完成)</STRONG><BR>好了，就像黑白电影总是会过渡到彩色电影一样（正巧，就像现在发生在移动电话市场的情况一样），cvs命令行之外，一些图形界面的程序被编写出来简化你的操作。由于CVS的协议是公开的，所以，只要你的编程语言支持socket通讯，你也可以写一个。这个世界上有好几个这样的尝试，WinCVS就是其中一个。它是在win32平台上用MFC开发的。从我自己的体会来看，这是一个有益的尝试，但是还远远称不上精美。和VSS和source off site，borland的tram source，以及PVCS的界面比较，这个windows界面还显得很粗糙，差强人意。 <BR>但是我们还是可以从它开始进行我们的工作。 <BR>下载请至http://www.redsaga.com/CVS_newbie_win32/www.cvsgui.org,那里有最新的版本。 <BR>打开开始菜单的之后，你看到的是这样一个界面： <BR><BR>界面由3个主要区域组成，坐上角是目录结构，右上角是文件夹详细内容，下方是CVS命令的log。你可以从下方的log中得知cvs运行的详细信息。 <BR><BR>首先你要做的事情就是告诉winCVS你的CVSROOT。 <BR><BR>这个对话框在winCVS1。2和1。3的各个版本中稍有不同，但是不妨碍你输入CVS服务器的详细信息。 <BR><BR>下一步就是login。 <BR><BR>好了，现在我们就可以去得到一份jive2的源代码了。 <BR><BR>你可以看到，winCVS默认会加上压缩的参数，这样可以减少网络流量，加快速度。 <BR><BR>同样，用winCVS进行文件修改也是挺方便的。 <BR><BR>以上就是winCVS的简要操作指南。更进一步的复杂操作，请参阅其帮助。 <BR><BR>评价：值得关注，但不推荐。 <BR><STRONG>在windows Explorer里直接checkout ---- TortoiseCVS</STRONG><BR>TortoiseCVS已经是一个相当成熟的cvs界面了，它的工作方式也是非常有趣的。 <BR>TortoiseCVS是一个简洁有效的CVS界面。你完全可以用它替代winCVS做日常绝大多数的工作。他独特的运行方式非常迷人，在一些商用配置管理工具，比如Rational ClearCase中，你也可以看到这样的windows explorer扩展程序的工作方式。 <BR>缺点： <BR>1,tortoiseCVS会一直不释放它所操作的一些CVS文件和文件夹的系统资源。你可能会在试图删除一个在CVS控制之下的目录时遇到麻烦。windows系统认为有另一个进程正在打开它（显然就是TortoiseCVS)，我没有找到如何杀掉在后台执行的TortoiseCVS的方法。在这种情况，用TortoiseCVS去update一下另一个module有所帮助。或者请重起你的explorer。 <BR>2,如果你需要在两个不同的server或者repository上做checkout的工作，TortoiseCVS有一个bug。它会在你输入CVSROOT信息，checkout第二个module的时候仍然使用第一个repository的CVSROOT。但是再做一次同样的操作就会成功的达到你的目的。 <BR>评价：推荐。 <BR>按此进入关于使用TortoiseCVS的详细说明 <BR><STRONG>基于Netbeans Java类库的漂亮GUI ---- SmartCVS</STRONG><BR>使用java编写的CVS GUI在过去一两年中得到了长足的发展。拜jdk1.3所托，现在java程序的执行速度也有很大提高。Netbeans是由sun赞助的一个开放IDE,它其中包含了了CVS的基础类库。一个商业性的GUI,SmartCVS,就是在netbeans的稳定的cvs核心之上编写的。 虽然SmartCVS的商业版本收费,但是其基础版本是完全免费的,而这个基础版本已经足够大多数应用所需。 <BR><BR>SmartCVS你可以在www.regnis.de下载。 <BR>SmartCVS自从1.2beta版本开始引入smartCommit,不再区分add和checkin,统一使用commit进行操作。 <BR><BR>利用SmartCVS,你也可以看到一个文件的历史,以及图形化表示的各个分支。 <BR><BR>总结:SmartCVS正如他的名字所说的,是一个相当聪明,精致,漂亮的CVS 客户端。作为日常工作它是完全可以胜任的。如果和TortoiesCVS结合起来,可以给你相当理想的CVS工作平台。 <BR>同时,它也可以在所有jdk环境中运行,不仅仅局限于windows平台。 <BR><BR><STRONG>IDE集成</STRONG><BR>对程序员来说,真正在编码的时候,IDE才是每天接触最多的环境。如果能够在熟悉的IDE中使用CVS,当然实用性增强很多。Visual source safe 在Microsoft的开发工具产品VB,VC中集成得相当出色,也大大提高了使用使用Microsoft开发平台的工作效率。 <BR>下面我们就来看看一下在流行的java开发工具中如何使用CVS。 <BR><BR><STRONG>IBM Visual age for java IDE集成 插件 --- vajcvs (未完成)</STRONG><BR>Visual age for java支持一个开放的Tool API,CVSin就是这样的一个tool。 <BR>下载地址: <BR><BR>安装参见其内部readme文件。 <BR><BR><STRONG>Borland jBuilder 内置CVS支持</STRONG><BR>jBuilder很早就在3.0中内置CVS支持,而且当时cvs是jbuilder唯一一个正式支持的源代码管理工具。在最新的Builder 6中,当然对CVS也支持得很好。 <BR><BR><STRONG>完善的设计，领先的强大工作平台 --- Eclipse</STRONG><BR>及内置CVS支持IBM新的开放式集成开发环境,将是IBM visual age 系列开发工具的下一个平台。它提供CVS作为基础集成的一部分。在Eclipse中访问CVS是一件相当轻松自如的事情，Eclipse按照自己的需要封装了CVS,你可以看到，和其他访问方式完全不同，Eclipse是到现在为止最强大的CVS工作平台。<img src ="http://www.blogjava.net/qq13367612/aggbug/17125.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-28 08:48 <a href="http://www.blogjava.net/qq13367612/articles/17125.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>LDAP介绍</title><link>http://www.blogjava.net/qq13367612/articles/16876.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 26 Oct 2005 07:46:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/16876.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/16876.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/16876.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/16876.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/16876.html</trackback:ping><description><![CDATA[<P><SPAN style="FONT-FAMILY: 宋体; Times: ">如果你在计算机行业工作，那么对</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">可能早有耳闻了。想深入地了解</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">吗？那么可以好好地读一下这篇文章。这篇介绍性的文章是一系列介绍如何在企业中设计、实现和集成</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">环境的文章的头一篇。主要是先让你熟悉一下</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的基本概念，那些比较困难的细节问题将放到以后讨论。在这篇文章中我们将要介绍：</SPAN></P>
<P><EM><STRONG><SPAN style="FONT-FAMILY: 宋体; Times: ">什么是LDAP?</SPAN></STRONG></EM></P>
<P><EM><STRONG><SPAN style="FONT-FAMILY: 宋体; Times: ">什么时候该用LDAP存储数据？</SPAN></STRONG></EM></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: "><STRONG><EM>LDAP目录树的结构</EM></STRONG></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">现在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">技术不仅发展得很快而且也是激动人心的。在企业范围内实现</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">可以让运行在几乎所有计算机平台上的所有的应用程序从</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录中获取信息。</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录中可以存储各种类型的数据：电子邮件地址、邮件路由信息、人力资源数据、公用密匙、联系人列表，等等。通过把</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录作为系统集成中的一个重要环节，可以简化员工在企业内部查询信息的步骤，甚至连主要的数据源都可以放在任何地方。如果</SPAN><SPAN lang=EN-US>Oracle</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">、</SPAN><SPAN lang=EN-US>Sybase</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">、</SPAN><SPAN lang=EN-US>Informix</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">或</SPAN><SPAN lang=EN-US>Microsoft SQL</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">数据库中已经存储了类似的数据，那么</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">和这些数据库到底有什么不同呢？是什么让它更具优势？请继续读下去吧！</SPAN></P>
<H2><A name=_什么是LDAP?></A><SPAN style="FONT-FAMILY: 黑体">什么是</SPAN><SPAN lang=EN-US>LDAP?</SPAN></H2>
<P><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的英文全称是</SPAN><SPAN lang=EN-US style="COLOR: black">Lightweight Directory Access Protocol</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: black">，一般都简称为</SPAN><SPAN lang=EN-US style="COLOR: black">LDAP</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">。它是基于</SPAN><SPAN lang=EN-US style="COLOR: black">X.500</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: black">标准的，但是简单多了并且可以根据需要定制。与</SPAN><SPAN lang=EN-US style="COLOR: black">X.500</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: black">不同，</SPAN><SPAN lang=EN-US style="COLOR: black">LDAP</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">支持</SPAN><SPAN lang=EN-US style="COLOR: black">TCP/IP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: black">，这对访问</SPAN><SPAN lang=EN-US style="COLOR: black">Internet</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: black">是必须的。</SPAN><SPAN lang=EN-US style="COLOR: black">LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: black">的核心规范在</SPAN><SPAN lang=EN-US style="COLOR: black">RFC</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: black">中都有定义，所有与</SPAN><SPAN lang=EN-US style="COLOR: black">LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: black">相关的</SPAN><SPAN lang=EN-US style="COLOR: black">RFC</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">都可以在</SPAN><SPAN lang=EN-US style="COLOR: black"><A href="http://www.ldapman.org/ldap_rfcs.html">LDAPman RFC</A></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: black">网页中找到。</SPAN></P>
<H3><SPAN style="FONT-FAMILY: 宋体; Times: ">怎么使用</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">这个术语呢？</SPAN></H3>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">在日常交谈中，你可能会听到有些人这么说：“我们要把那些东西存在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">中吗？”，或者“从</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">数据库中取出那些数据！”，又或者“我们怎么把</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">和关系型数据库集成在一起？”。严格地说，</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">根本不是数据库而是用来访问存储在信息目录（也就是</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录）中的信息的<B>协议</B>。更为确切和正式的说法应该是象这样的：“通过使用</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">，可以在信息目录的正确位置读取（或存储）数据”。但是，也没有必要吹毛求疵，尽管表达得不够准确，我们也都知道对方在说什么。</SPAN></P>
<H3><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录是数据库吗？</SPAN></H3>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">就象</SPAN><SPAN lang=EN-US>Sybase</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">、</SPAN><SPAN lang=EN-US>Oracle</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">、</SPAN><SPAN lang=EN-US>Informix</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">或</SPAN><SPAN lang=EN-US>Microsoft</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的数据库管理系统（</SPAN><SPAN lang=EN-US>DBMS</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）是用于处理查询和更新关系型数据库那样，</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器也是用来处理查询和更新</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录的。换句话来说</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录也是<B>一种类型</B>的数据库，但是不是关系型数据库。不象被设计成每分钟需要处理成百上千条数据变化的数据库，例如：在电子商务中经常用到的在线交易处理（</SPAN><SPAN lang=EN-US>OLTP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）系统，</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">主要是优化数据读取的性能。</SPAN></P>
<H3><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录的优势</SPAN></H3>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">现在该说说</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录到底有些什么优势了。现在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的流行是很多因数共同作用的结果。我在这里说的不过是一些基本的原因，请你注意一下这不过是一小部分原因。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">可能</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">最大的优势是：可以在任何计算机平台上，用很容易获得的而且数目不断增加的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的客户端程序访问</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录。而且也很容易定制应用程序为它加上</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的支持。</SPAN></P>
<P><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">协议是跨平台的和标准的协议，因此应用程序就不用为</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录放在什么样的服务器上操心了。实际上，</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">得到了业界的广泛认可，因为它是</SPAN><SPAN lang=EN-US>Internet</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的标准。产商都很愿意在产品中加入对</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的支持，因为他们根本不用考虑另一端（客户端或服务端）是怎么样的。</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器可以是任何一个开发源代码或商用的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录服务器（或者还可能是具有</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">界面的关系型数据库），因为可以用同样的协议、客户端连接软件包和查询命令与</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器进行交互。与</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">不同的是，如果软件产商想在软件产品中集成对</SPAN><SPAN lang=EN-US>DBMS</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的支持，那么通常都要对每一个数据库服务器单独定制。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">不象很多商用的关系型数据库，你不必为</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的每一个客户端连接或许可协议付费。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">大多数的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器安装起来很简单，也容易维护和优化。</SPAN></P>
<P><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器可以用“推”或“拉”的方法复制部分或全部数据，例如：可以把数据“推”到远程的办公室，以增加数据的安全性。复制技术是内置在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器中的而且很容易配置。如果要在</SPAN><SPAN lang=EN-US>DBMS</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">中使用相同的复制功能，数据库产商就会要你支付额外的费用，而且也很难管理。</SPAN></P>
<P><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">允许你根据需要使用</SPAN><SPAN lang=EN-US>ACI</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">（一般都称为</SPAN><SPAN lang=EN-US>ACL</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">或者访问控制列表）控制对数据读和写的权限。例如，设备管理员可以有权改变员工的工作地点和办公室号码，但是不允许改变记录中其它的域。</SPAN><SPAN lang=EN-US>ACI</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">可以根据谁访问数据、访问什么数据、数据存在什么地方以及其它对数据进行访问控制。因为这些都是由</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录服务器完成的，所以不用担心在客户端的应用程序上是否要进行安全检查。</SPAN></P>
<P><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">对于这样存储这样的信息最为有用，也就是数据需要从不同的地点读取，但是不需要经常更新。例如，这些信息存储在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录中是十分有效的：</SPAN></P>
<P class=MsoListBullet><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">公司员工的电话号码簿和组织结构图</SPAN></P>
<P class=MsoListBullet><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">客户的联系信息</SPAN></P>
<P class=MsoListBullet><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">计算机管理需要的信息，包括</SPAN><SPAN lang=EN-US>NIS</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">映射、</SPAN><SPAN lang=EN-US>email</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">假名，等等</SPAN></P>
<P class=MsoListBullet><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">软件包的配置信息</SPAN></P>
<P class=MsoListBullet><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">公用证书和安全密匙</SPAN></P>
<H2><A name=_什么时候该用LDAP存储数据></A><A name=_什么时候该用LDAP存储数据？></A><SPAN style="FONT-FAMILY: 黑体">什么时候该用</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 黑体">存储数据？</SPAN></H2>
<P><SPAN style="COLOR: black; FONT-FAMILY: 宋体">大多数的</SPAN><SPAN lang=EN-US style="COLOR: black">LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: black">服务器都为读密集型的操作进行专门的优化。因此，当从</SPAN><SPAN lang=EN-US style="COLOR: black">LDAP</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">服务器中读取数据的时候会比从专门为</SPAN><SPAN lang=EN-US style="COLOR: black">OLTP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: black">优化的关系型数据库中读取数据快一个数量级。也是因为专门为读的性能进行优化，大多数的</SPAN><SPAN lang=EN-US style="COLOR: black">LDAP</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">目录服务器并不适合存储需要需要经常改变的数据。例如，用</SPAN><SPAN lang=EN-US style="COLOR: black">LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: black">服务器来存储电话号码是一个很好的选择，但是它不能作为电子商务站点的数据库服务器。</SPAN><SPAN lang=EN-US style="COLOR: black"></SPAN></P>
<P><SPAN style="COLOR: black; FONT-FAMILY: 宋体">如果下面每一个问题的答案都是“是”，那么把数据存在</SPAN><SPAN lang=EN-US style="COLOR: black">LDAP</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">中就是一个好主意。</SPAN><SPAN lang=EN-US style="COLOR: black"></SPAN></P>
<P class=MsoListBullet><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">需要在任何平台上都能读取数据吗？</SPAN></P>
<P class=MsoListBullet><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">每一个单独的记录项是不是每一天都只有很少的改变？</SPAN></P>
<P class=MsoListBullet><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">可以把数据存在平面数据库（</SPAN><SPAN lang=EN-US>flat database</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）而不是关系型数据库中吗？换句话来说，也就是不管什么范式不范式的，把所有东西都存在一个记录中（差不多只要满足第一范式）。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">最后一个问题可能会唬住一些人，其实用平面数据库去存储一些关系型的数据也是很一般的。例如，一条公司员工的记录就可以包含经理的登录名。用</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">来存储这类信息是很方便的。一个简单的判断方法：如果可以把保数据存在一张张的卡片里，就可以很容易地把它存在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录里。</SPAN></P>
<H2><A name=_LDAP目录树的结构></A><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 黑体">目录树的结构</SPAN></H2>
<P><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录以树状的层次结构来存储数据。如果你对自顶向下的</SPAN><SPAN lang=EN-US>DNS</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">树或</SPAN><SPAN lang=EN-US>UNIX</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">文件的目录树比较熟悉，也就很容易掌握</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录树这个概念了。就象</SPAN><SPAN lang=EN-US>DNS</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的主机名那样，</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录记录的标识名（</SPAN><SPAN lang=EN-US>Distinguished Name</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">，简称</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）是用来读取单个记录，以及回溯到树的顶部。后面会做详细地介绍。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">为什么要用层次结构来组织数据呢？原因是多方面的。下面是可能遇到的一些情况：</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">如果你想把所有的美国客户的联系信息都“推”到位于到西雅图办公室（负责营销）的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器上，但是你不想把公司的资产管理信息“推”到那里。</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">你可能想根据目录树的结构给予不同的员工组不同的权限。在下面的例子里，资产管理组对“</SPAN><SPAN lang=EN-US>asset-mgmt</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">”部分有完全的访问权限，但是不能访问其它地方。</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">把</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">存储和复制功能结合起来，可以定制目录树的结构以降低对</SPAN><SPAN lang=EN-US>WAN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">带宽的要求。位于西雅图的营销办公室需要每分钟更新的美国销售状况的信息，但是欧洲的销售情况就只要每小时更新一次就行了。</SPAN></P>
<H3><SPAN style="FONT-FAMILY: 宋体; Times: ">刨根问底：基准</SPAN><SPAN lang=EN-US>DN</SPAN></H3>
<P><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录树的最顶部就是根，也就是所谓的“基准</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">”。基准</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">通常使用下面列出的三种格式之一。假定我在名为</SPAN><SPAN lang=EN-US>FooBar</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的电子商务公司工作，这家公司在</SPAN><SPAN lang=EN-US>Internet</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">上的名字是</SPAN><SPAN lang=EN-US>foobar.com</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。</SPAN></P>
<P class=a><B><SPAN lang=EN-US>o="FooBar, Inc.", c=US </SPAN></B></P>
<P><I><SPAN style="COLOR: black; FONT-FAMILY: 宋体">（以</SPAN><SPAN lang=EN-US style="COLOR: black">X.500</SPAN></I><I><SPAN style="FONT-FAMILY: 宋体; Times: black">格式表示的基准</SPAN><SPAN lang=EN-US style="COLOR: black">DN</SPAN></I><I><SPAN style="COLOR: black; FONT-FAMILY: 宋体">）</SPAN><SPAN lang=EN-US style="COLOR: black"></SPAN></I></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">在这个例子中，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">o=FooBar, Inc. </SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">表示组织名，在这里就是公司名的同义词。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">c=US </SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">表示公司的总部在美国。以前，一般都用这种方式来表示基准</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。但是事物总是在不断变化的，现在所有的公司都已经（或计划）上</SPAN><SPAN lang=EN-US>Internet</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">上。随着</SPAN><SPAN lang=EN-US>Internet</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的全球化，在基准</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">中使用国家代码很容易让人产生混淆。现在，</SPAN><SPAN lang=EN-US>X.500</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">格式发展成下面列出的两种格式。</SPAN></P>
<P class=a><B><SPAN lang=EN-US>o=foobar.com</SPAN></B></P>
<P><I><SPAN style="FONT-FAMILY: 宋体; Times: ">（用公司的</SPAN><SPAN lang=EN-US>Internet</SPAN></I><I><SPAN style="FONT-FAMILY: 宋体; Times: ">地址表示的基准</SPAN><SPAN lang=EN-US>DN</SPAN></I><I><SPAN style="FONT-FAMILY: 宋体; Times: ">）</SPAN><SPAN lang=EN-US></SPAN></I></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">这种格式很直观，用公司的域名作为基准</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。这也是现在最常用的格式。</SPAN></P>
<P class=a><B><SPAN lang=EN-US>dc=foobar, dc=com</SPAN></B></P>
<P><I><SPAN style="FONT-FAMILY: 宋体; Times: ">（用</SPAN><SPAN lang=EN-US>DNS</SPAN></I><I><SPAN style="FONT-FAMILY: 宋体; Times: ">域名的不同部分组成的基准</SPAN><SPAN lang=EN-US>DN</SPAN></I><I><SPAN style="FONT-FAMILY: 宋体; Times: ">）</SPAN><SPAN lang=EN-US></SPAN></I></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">就象上面那一种格式，这种格式也是以</SPAN><SPAN lang=EN-US>DNS</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">域名为基础的，但是上面那种格式不改变域名（也就更易读），而这种格式把域名：</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">foobar.com</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">分成两部分</SPAN> <SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">dc=foobar, dc=com</SPAN><SPAN style="FONT-SIZE: 10.5pt; FONT-FAMILY: 黑体; Courier: black">。</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">在理论上，这种格式可能会更灵活一点，但是对于最终用户来说也更难记忆一点。考虑一下</SPAN><SPAN lang=EN-US>foobar.com</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">这个例子。当</SPAN><SPAN lang=EN-US>foobar.com</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">和</SPAN><SPAN lang=EN-US>gizmo.com</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">合并之后，可以简单的把“</SPAN><SPAN lang=EN-US>dc=com</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">”当作基准</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。把新的记录放到已经存在的</SPAN><SPAN lang=EN-US>dc=gizmo, dc=com</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录下，这样就简化了很多工作（当然，如果</SPAN><SPAN lang=EN-US>foobar.com</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">和</SPAN><SPAN lang=EN-US>wocket.edu</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">合并，这个方法就不能用了）。如果</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器是新安装的，我建议你使用这种格式。再请注意一下，如果你打算使用活动目录（</SPAN><SPAN lang=EN-US>Actrive Directory</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">），</SPAN><SPAN lang=EN-US>Microsoft</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">已经限制你必须使用这种格式。</SPAN></P>
<H3><SPAN style="FONT-FAMILY: 宋体; Times: ">更上一层楼：在目录树中怎么组织数据</SPAN></H3>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">在</SPAN><SPAN lang=EN-US>UNIX</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">文件系统中，最顶层是根目录（</SPAN><SPAN lang=EN-US>root</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）。在根目录的下面有很多的文件和目录。象上面介绍的那样，</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录也是用同样的方法组织起来的。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">在根目录下，要把数据从逻辑上区分开。因为历史上（</SPAN><SPAN lang=EN-US>X.500</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）的原因，大多数</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录用</SPAN><SPAN lang=EN-US>OU</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">从逻辑上把数据分开来。</SPAN><SPAN lang=EN-US>OU</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">表示“</SPAN><SPAN lang=EN-US>Organization Unit</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">”，在</SPAN><SPAN lang=EN-US>X.500</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">协议中是用来表示公司内部的机构：销售部、财务部，等等。现在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">还保留</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">ou=</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">这样的命名规则，但是扩展了分类的范围，可以分类为：</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">ou=people, ou=groups, ou=devices</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: black">，等等。更低一级的</SPAN><SPAN lang=EN-US style="COLOR: black">OU</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: black">有时用来做更细的归类。例如：</SPAN><SPAN lang=EN-US style="COLOR: black">LDAP</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">目录树（不包括单独的记录）可能会是这样的：</SPAN><SPAN lang=EN-US style="COLOR: black"></SPAN></P>
<P class=a><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>dc=foobar, dc=com </P>
<P class=a><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>ou=customers </P>
<P class=a><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>ou=asia </P>
<P class=a><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>ou=europe </P>
<P class=a><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>ou=usa </P>
<P class=a><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>ou=employees </P>
<P class=a><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>ou=rooms </P>
<P class=a><SPAN>&nbsp;&nbsp; </SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ou=groups </P>
<P class=a><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>ou=assets-mgmt </P>
<P class=a><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>ou=nisgroups </P>
<P class=a><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>ou=recipes<BR><BR></P>
<P><EM><STRONG><SPAN style="FONT-FAMILY: 宋体; Times: ">单独的LDAP记录</SPAN></STRONG></EM></P>
<P><EM><STRONG><SPAN style="FONT-FAMILY: 宋体; Times: ">作为例子的一个单独的数据项</SPAN></STRONG></EM></P>
<P><EM><STRONG><SPAN style="FONT-FAMILY: 宋体; Times: ">LDAP复制</SPAN></STRONG></EM></P>
<P><STRONG><EM><SPAN style="FONT-FAMILY: 宋体; Times: ">安全和访问控制<BR></SPAN></EM></STRONG></P><SPAN style="FONT-FAMILY: 宋体; Times: ">
<H2><A name=_单独的LDAP记录></A><SPAN style="FONT-FAMILY: 黑体">单独的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 黑体">记录</SPAN></H2>
<H3><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">是</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">记录项的名字</SPAN></H3>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录中的所有记录项都有一个唯一的“</SPAN><SPAN lang=EN-US>Distinguished Name</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">”，也就是</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。每一个</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">记录项的</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">是由两个部分组成的：相对</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">（</SPAN><SPAN lang=EN-US>RDN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）和记录在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录中的位置。</SPAN></P>
<P><SPAN lang=EN-US>RDN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">是</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">中与目录树的结构无关的部分。在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录中存储的记录项都要有一个名字，这个名字通常存在</SPAN><SPAN lang=EN-US>cn</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">（</SPAN><SPAN lang=EN-US>Common Name</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）这个属性里。因为几乎所有的东西都有一个名字，在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">中存储的对象都用它们的</SPAN><SPAN lang=EN-US>cn</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">值作为</SPAN><SPAN lang=EN-US>RDN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的基础。如果我把最喜欢的吃燕麦粥食谱存为一个记录，我就会用</SPAN><B><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">cn=Oatmeal Deluxe</SPAN></B><SPAN style="FONT-FAMILY: 宋体; Times: ">作为记录项的</SPAN><SPAN lang=EN-US>RDN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。</SPAN></P>
<P><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">我的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录的基准</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">是</SPAN><B><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">dc=foobar,dc=com</SPAN></B></P>
<P><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">我把自己的食谱作为</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的记录项存在</SPAN><B><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">ou=recipes</SPAN></B></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">我的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">记录项的</SPAN><SPAN lang=EN-US>RDN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">设为</SPAN><B><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">cn=Oatmeal Deluxe</SPAN></B></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">上面这些构成了燕麦粥食谱的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">记录的完整</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。记住，</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的读法和</SPAN><SPAN lang=EN-US>DNS</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">主机名类似。下面就是完整的</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">：</SPAN></P>
<P class=a><B><SPAN lang=EN-US>cn=Oatmeal Deluxe,ou=recipes,dc=foobar,dc=com</SPAN></B></P>
<H3><SPAN style="FONT-FAMILY: 宋体; Times: ">举一个实际的例子来说明</SPAN><SPAN lang=EN-US>DN</SPAN></H3>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">现在为公司的员工设置一个</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。可以用基于</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">cn</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">或</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">uid</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">（</SPAN><SPAN lang=EN-US>User ID</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">），作为典型的用户帐号。例如，</SPAN><SPAN lang=EN-US>FooBar</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的员工</SPAN><SPAN lang=EN-US>Fran Smith</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">（登录名：</SPAN><SPAN lang=EN-US>fsmith</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）的</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">可以为下面两种格式：</SPAN></P>
<P class=a><B><SPAN lang=EN-US>uid=fsmith,ou=employees,dc=foobar,dc=com</SPAN></B></P>
<P><I><SPAN style="FONT-FAMILY: 宋体; Times: ">（基于登录名）</SPAN><SPAN lang=EN-US></SPAN></I></P>
<P><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">（以及</SPAN><SPAN lang=EN-US>X.500</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）用</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">uid</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">表示“</SPAN><SPAN lang=EN-US>User ID</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">”，不要把它和</SPAN><SPAN lang=EN-US>UNIX</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的</SPAN><SPAN lang=EN-US>uid</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">号混淆了。大多数公司都会给每一个员工唯一的登录名，因此用这个办法可以很好地保存员工的信息。你不用担心以后还会有一个叫</SPAN><SPAN lang=EN-US>Fran Smith</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的加入公司，如果</SPAN><SPAN lang=EN-US>Fran</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">改变了她的名字（结婚？离婚？或宗教原因？），也用不着改变</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">记录项的</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。</SPAN></P>
<P class=a><B><SPAN lang=EN-US>cn=Fran Smith,ou=employees,dc=foobar,dc=com</SPAN></B></P>
<P><I><SPAN style="FONT-FAMILY: 宋体; Times: ">（基于姓名）</SPAN><SPAN lang=EN-US></SPAN></I></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">可以看到这种格式使用了</SPAN><SPAN lang=EN-US>Common Name</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">（</SPAN><SPAN lang=EN-US>CN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）。可以把</SPAN><SPAN lang=EN-US>Common Name</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">当成一个人的全名。这种格式有一个很明显的缺点就是：如果名字改变了，</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的记录就要从一个</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">转移到另一个</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。但是，我们应该尽可能地避免改变一个记录项的</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。</SPAN></P>
<H2><SPAN style="FONT-FAMILY: 黑体">定制目录的对象类型</SPAN></H2>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">你可以用</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">存储各种类型的数据对象，只要这些对象可以用属性来表示，下面这些是可以在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">中存储的一些信息：</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">员工信息：员工的姓名、登录名、口令、员工号、他的经理的登录名，邮件服务器，等等。</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">物品跟踪信息：计算机名、</SPAN><SPAN lang=EN-US>IP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">地址、标签、型号、所在位置，等等。</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">客户联系列表：客户的公司名、主要联系人的电话、传真和电子邮件，等等。</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">会议厅信息：会议厅的名字、位置、可以坐多少人、电话号码、是否有投影机。</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">食谱信息：菜的名字、配料、烹调方法以及准备方法。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">因为</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录可以定制成存储任何文本或二进制数据，到底存什么要由你自己决定。</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录用对象类型（</SPAN><SPAN lang=EN-US>object classes</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）的概念来定义运行哪一类的对象使用什么属性。在几乎所有的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器中，你都要根据自己的需要扩展基本的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录的功能，创建新的对象类型或者扩展现存的对象类型。</SPAN></P>
<P><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录以一系列“属性对”的形式来存储记录项，每一个记录项包括属性类型和属性值（这与关系型数据库用行和列来存取数据有根本的不同）。下面是我存在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录中的一部分食谱记录：</SPAN></P>
<P class=a><SPAN>&nbsp; </SPAN>dn: cn=Oatmeal Deluxe, ou=recipes, dc=foobar, dc=com </P>
<P class=a><SPAN>&nbsp; </SPAN>cn: Instant Oatmeal Deluxe </P>
<P class=a><SPAN>&nbsp; </SPAN>recipeCuisine: breakfast </P>
<P class=a><SPAN>&nbsp; </SPAN>recipeIngredient: 1 packet instant oatmeal </P>
<P class=a><SPAN>&nbsp; </SPAN>recipeIngredient: 1 cup water </P>
<P class=a><SPAN>&nbsp; </SPAN>recipeIngredient: 1 pinch salt </P>
<P class=a><SPAN>&nbsp; </SPAN>recipeIngredient: 1 tsp brown sugar </P>
<P class=a><SPAN>&nbsp; </SPAN>recipeIngredient: 1/4 apple, any type</P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">请注意上面每一种配料都作为属性</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">recipeIngredient</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">值。</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录被设计成象上面那样为一个属性保存多个值的，而不是在每一个属性的后面用逗号把一系列值分开。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">因为用这样的方式存储数据，所以数据库就有很大的灵活性，不必为加入一些新的数据就重新创建表和索引。更重要的是，</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录不必花费内存或硬盘空间处理“空”域，也就是说，实际上不使用可选择的域也不会花费你任何资源。</SPAN></P>
<H2><A name=_作为例子的一个单独的数据项></A><SPAN style="FONT-FAMILY: 黑体">作为例子的一个单独的数据项</SPAN></H2>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">让我们看看下面这个例子。我们用</SPAN><SPAN lang=EN-US>Foobar, Inc.</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的员工</SPAN><SPAN lang=EN-US>Fran Smith</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">记录。这个记录项的格式是</SPAN><SPAN lang=EN-US>LDIF</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">，用来导入和导出</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录的记录项。</SPAN></P>
<P class=a><SPAN>&nbsp; </SPAN>dn: uid=fsmith, ou=employees, dc=foobar, dc=com</P>
<P class=a><SPAN>&nbsp; </SPAN>objectclass: person</P>
<P class=a><SPAN>&nbsp; </SPAN>objectclass: organizationalPerson</P>
<P class=a><SPAN>&nbsp; </SPAN>objectclass: inetOrgPerson</P>
<P class=a><SPAN>&nbsp; </SPAN>objectclass: foobarPerson</P>
<P class=a><SPAN>&nbsp; </SPAN>uid: fsmith</P>
<P class=a><SPAN>&nbsp; </SPAN>givenname: Fran</P>
<P class=a><SPAN>&nbsp; </SPAN>sn: Smith</P>
<P class=a><SPAN>&nbsp; </SPAN>cn: Fran Smith</P>
<P class=a><SPAN>&nbsp;</SPAN>&nbsp;cn: Frances Smith</P>
<P class=a><SPAN>&nbsp; </SPAN>telephonenumber: 510-555-1234</P>
<P class=a><SPAN>&nbsp; </SPAN>roomnumber: 122G</P>
<P class=a><SPAN>&nbsp; </SPAN>o: Foobar, Inc.</P>
<P class=a><SPAN>&nbsp; </SPAN>mailRoutingAddress: fsmith@foobar.com</P>
<P class=a><SPAN>&nbsp; </SPAN>mailhost: mail.foobar.com</P>
<P class=a><SPAN>&nbsp; </SPAN>userpassword: {crypt}3x1231v76T89N</P>
<P class=a><SPAN>&nbsp; </SPAN>uidnumber: 1234</P>
<P class=a><SPAN>&nbsp; </SPAN>gidnumber: 1200</P>
<P class=a><SPAN>&nbsp; </SPAN>homedirectory: /home/fsmith</P>
<P class=a><SPAN>&nbsp; </SPAN>loginshell: /usr/local/bin/bash</P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">属性的值在保存的时候是保留大小写的，但是在默认情况下搜索的时候是不区分大小写的。某些特殊的属性（例如，</SPAN><SPAN lang=EN-US>password</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）在搜索的时候需要区分大小写。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">让我们一点一点地分析上面的记录项。</SPAN></P>
<P class=a><SPAN lang=EN-US>dn: uid=fsmith, ou=employees, dc=foobar, dc=com</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">这是</SPAN><SPAN lang=EN-US>Fran</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">记录项的完整</SPAN><SPAN lang=EN-US>DN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">，包括在目录树中的完整路径。</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">（和</SPAN><SPAN lang=EN-US>X.500</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）使用</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">uid</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">（</SPAN><SPAN lang=EN-US>User ID</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">），不要把它和</SPAN><SPAN lang=EN-US>UNIX</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的</SPAN><SPAN lang=EN-US>uid</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">号混淆了。</SPAN></P>
<P class=a><SPAN>&nbsp; </SPAN>objectclass: person </P>
<P class=a><SPAN>&nbsp; </SPAN>objectclass: organizationalPerson </P>
<P class=a><SPAN>&nbsp; </SPAN>objectclass: inetOrgPerson </P>
<P class=a><SPAN>&nbsp; </SPAN>objectclass: foobarPerson</P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">可以为任何一个对象根据需要分配多个对象类型。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">person</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">对象类型要求</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">cn</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">（</SPAN><SPAN lang=EN-US>common name</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）和</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">sn</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">（</SPAN><SPAN lang=EN-US>surname</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）这两个域不能为空。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">persion</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">对象类型允许有其它的可选域，包括</SPAN><SPAN lang=EN-US>givenname</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">、</SPAN><SPAN lang=EN-US>telephonenumber</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">，等等。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">organizational Person</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">给</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">person</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">加入更多的可选域，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">inetOrgPerson</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">又加入更多的可选域（包括电子邮件信息）。最后，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">foobarPerson</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">是为</SPAN><SPAN lang=EN-US>Foobar</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">定制的对象类型，加入了很多定制的属性。</SPAN></P>
<P class=a><SPAN>&nbsp; </SPAN>uid: fsmith </P>
<P class=a><SPAN>&nbsp; </SPAN>givenname: Fran </P>
<P class=a><SPAN>&nbsp; </SPAN>sn: Smith </P>
<P class=a><SPAN>&nbsp; </SPAN>cn: Fran Smith </P>
<P class=a><SPAN>&nbsp; </SPAN>cn: Frances Smith </P>
<P class=a><SPAN>&nbsp; </SPAN>telephonenumber: 510-555-1234 </P>
<P class=a><SPAN>&nbsp; </SPAN>roomnumber: 122G </P>
<P class=a><SPAN>&nbsp; </SPAN>o: Foobar, Inc.</P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">以前说过了，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">uid</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">表示</SPAN><SPAN lang=EN-US>User ID</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。当看到</SPAN><SPAN lang=EN-US>uid</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的时候，就在脑袋里想一想“</SPAN><SPAN lang=EN-US>login</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">”。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">请注意</SPAN><SPAN lang=EN-US>CN</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">有多个值。就象上面介绍的，</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">允许某些属性有多个值。为什么允许有多个值呢？假定你在用公司的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器查找</SPAN><SPAN lang=EN-US>Fran</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的电话号码。你可能只知道她的名字叫</SPAN><SPAN lang=EN-US>Fran</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">，但是对人力资源处的人来说她的正式名字叫做</SPAN><SPAN lang=EN-US>Frances</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。因为保存了她的两个名字，所以用任何一个名字检索都可以找到</SPAN><SPAN lang=EN-US>Fran</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的电话号码、电子邮件和办公房间号，等等。</SPAN></P>
<P class=a><SPAN>&nbsp; </SPAN>mailRoutingAddress: fsmith@foobar.com </P>
<P class=a><SPAN>&nbsp; </SPAN>mailhost: mail.foobar.com</P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">就象现在大多数的公司都上网了，</SPAN><SPAN lang=EN-US>Foobar</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">用</SPAN><SPAN lang=EN-US>Sendmail</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">发送邮件和处理外部邮件路由信息。</SPAN><SPAN lang=EN-US>Foobar</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">把所有用户的邮件信息都存在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">中。最新版本的</SPAN><SPAN lang=EN-US>Sendmail</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">支持这项功能。</SPAN></P>
<P class=a><SPAN>&nbsp; </SPAN>Userpassword: {crypt}3x1231v76T89N </P>
<P class=a><SPAN>&nbsp; </SPAN>uidnumber: 1234 </P>
<P class=a><SPAN>&nbsp; </SPAN>gidnumber: 1200 </P>
<P class=a><SPAN>&nbsp; </SPAN>gecos: Frances Smith </P>
<P class=a><SPAN>&nbsp; </SPAN>homedirectory: /home/fsmith </P>
<P class=a><SPAN>&nbsp; </SPAN>loginshell: /usr/local/bin/bash</P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">注意，</SPAN><SPAN lang=EN-US>Foobar</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的系统管理员把所有用户的口令映射信息也都存在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">中。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">FoobarPerson</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">类型的对象具有这种能力。再注意一下，用户口令是用</SPAN><SPAN lang=EN-US>UNIX</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的口令加密格式存储的。</SPAN><SPAN lang=EN-US>UNIX</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的</SPAN><SPAN lang=EN-US>uid</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">在这里为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 'Courier New'">uidnumber</SPAN><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 黑体">。</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">提醒你一下，关于如何在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">中保存</SPAN><SPAN lang=EN-US>NIS</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">信息，有完整的一份</SPAN><SPAN lang=EN-US>RFC</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。在以后的文章中我会谈一谈</SPAN><SPAN lang=EN-US>NIS</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的集成。</SPAN></P>
<H2><A name=_LDAP复制></A><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 黑体">复制</SPAN></H2>
<P><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器可以使用基于“推”或者“拉”的技术，用简单或基于安全证书的安全验证，复制一部分或者所有的数据。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">例如，</SPAN><SPAN lang=EN-US>Foobar</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">有一个“公用的”</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器，地址为</SPAN><SPAN lang=EN-US>ldap.foobar.com</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">，端口为</SPAN><SPAN lang=EN-US>389</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。</SPAN><SPAN lang=EN-US>Netscape Communicator</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的电子邮件查询功能、</SPAN><SPAN lang=EN-US>UNIX</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的“</SPAN><SPAN lang=EN-US>ph</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">”命令要用到这个服务器，用户也可以在任何地方查询这个服务器上的员工和客户联系信息。公司的主</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器运行在相同的计算机上，不过端口号是</SPAN><SPAN lang=EN-US>1389</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">你可能即不想让员工查询资产管理或食谱的信息，又不想让信息技术人员看到整个公司的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录。为了解决这个问题，</SPAN><SPAN lang=EN-US>Foobar</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">有选择地把子目录树从主</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器复制到“公用”</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器上，不复制需要隐藏的信息。为了保持数据始终是最新的，主目录服务器被设置成即时“推”同步。这些种方法主要是为了方便，而不是安全，因为如果有权限的用户想查询所有的数据，可以用另一个</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">端口。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">假定</SPAN><SPAN lang=EN-US>Foobar</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">通过从奥克兰到欧洲的低带宽数据的连接用</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">管理客户联系信息。可以建立从</SPAN><SPAN lang=EN-US>ldap.foobar.com:1389</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">到</SPAN><SPAN lang=EN-US>munich-ldap.foobar.com:389</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的数据复制，象下面这样：</SPAN></P>
<P class=a><SPAN>&nbsp; </SPAN>periodic pull: ou=asia,ou=customers,o=sendmail.com</P>
<P class=a><SPAN>&nbsp; </SPAN>periodic pull: ou=us,ou=customers,o=sendmail.com</P>
<P class=a><SPAN>&nbsp; </SPAN>immediate push: ou=europe,ou=customers,o=sendmail.com</P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">“拉”连接每</SPAN><SPAN lang=EN-US>15</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">分钟同步一次，在上面假定的情况下足够了。“推”连接保证任何欧洲的联系信息发生了变化就立即被“推”到</SPAN><SPAN lang=EN-US>Munich</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">用上面的复制模式，用户为了访问数据需要连接到哪一台服务器呢？在</SPAN><SPAN lang=EN-US>Munich</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的用户可以简单地连接到本地服务器。如果他们改变了数据，本地的</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器就会把这些变化传到主</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器。然后，主</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器把这些变化“推”回本地的“公用”</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器保持数据的同步。这对本地的用户有很大的好处，因为所有的查询（大多数是读）都在本地的服务器上进行，速度非常快。当需要改变信息的时候，最终用户不需要重新配置客户端的软件，因为</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录服务器为他们完成了所有的数据交换工作。</SPAN></P>
<H2><A name=_安全和访问控制></A><SPAN style="FONT-FAMILY: 黑体">安全和访问控制</SPAN></H2>
<P><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">提供很复杂的不同层次的访问控制或者</SPAN><SPAN lang=EN-US>ACI</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。因这些访问可以在服务器端控制，这比用客户端的软件保证数据的安全可安全多了。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">用</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">的</SPAN><SPAN lang=EN-US>ACI</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">，可以完成：</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">给予用户改变他们自己的电话号码和家庭地址的权限，但是限制他们对其它数据（如，职务名称，经理的登录名，等等）只有“只读”权限。</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">给予“</SPAN><SPAN lang=EN-US>HR-admins</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">”组中的所有人权限以改变下面这些用户的信息：经理、工作名称、员工号、部门名称和部门号。但是对其它域没有写权限。</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">禁止任何人查询</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器上的用户口令，但是可以允许用户改变他或她自己的口令。</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">给予经理访问他们上级的家庭电话的只读权限，但是禁止其他人有这个权限。</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">给予“</SPAN><SPAN lang=EN-US>host-admins</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">”组中的任何人创建、删除和编辑所有保存在</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">服务器中的与计算机主机有关的信息</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">通过</SPAN><SPAN lang=EN-US>Web</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">，允许“</SPAN><SPAN lang=EN-US>foobar-sales</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">”组中的成员有选择地给予或禁止他们自己读取一部分客户联系数据的读权限。这将允许他们把客户联系信息下载到本地的笔记本电脑或个人数字助理（</SPAN><SPAN lang=EN-US>PDA</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）上。（如果销售人员的软件都支持</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">，这将非常有用）</SPAN></P>
<P><SPAN lang=EN-US style="FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">通过</SPAN><SPAN lang=EN-US>Web</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">，允许组的所有者删除或添加他们拥有的组的成员。例如：可以允许销售经理给予或禁止销售人员改变</SPAN><SPAN lang=EN-US>Web</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">页的权限。也可以允许邮件假名（</SPAN><SPAN lang=EN-US>mail aliase</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">）的所有者不经过</SPAN><SPAN lang=EN-US>IT</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">技术人员就直接从邮件假名中删除或添加用户。“公用”的邮件列表应该允许用户从邮件假名中添加或删除自己（但是只能是自己）。也可以对</SPAN><SPAN lang=EN-US>IP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">地址或主机名加以限制。例如，某些域只允许用户</SPAN><SPAN lang=EN-US>IP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">地址以</SPAN><SPAN lang=EN-US>192.168.200.*</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">开头的有读的权限，或者用户反向查找</SPAN><SPAN lang=EN-US>DNS</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">得到的主机名必须为</SPAN><SPAN lang=EN-US>*.foobar.com</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体; Times: ">这不过是让你了解一下可以对</SPAN><SPAN lang=EN-US>LDAP</SPAN><SPAN style="FONT-FAMILY: 宋体; Times: ">目录进行怎样的访问控制，实际上真正实现起来需要做的工作比这多得多。在以后的文章中我会详细地讨论访问控制。</SPAN></P></SPAN><img src ="http://www.blogjava.net/qq13367612/aggbug/16876.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-26 15:46 <a href="http://www.blogjava.net/qq13367612/articles/16876.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CVS使用手册</title><link>http://www.blogjava.net/qq13367612/articles/16666.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Mon, 24 Oct 2005 14:23:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/16666.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/16666.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/16666.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/16666.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/16666.html</trackback:ping><description><![CDATA[<P>内容摘要： </P>
<P>CVS是一个C/S系统，多个开发人员通过一个中心版本控制系统来记录文件版本，从而达到保证文件同步的目的。工作模式如下： </P><PRE>       CVS服务器（文件版本库）
     /     |       \
     （版 本 同 步）
   /       |         \
开发者1  开发者2   开发者3
</PRE>
<P>作为一般开发人员挑选2,6看就可以了，CVS的管理员则更需要懂的更多一些，最后还简单介绍了一些Windows下的cvs客户端使用，CVS远程用户认证的选择及与BUG跟踪系统等开发环境的集成问题。</P>
<OL>
<LI><A href="http://www.chedong.com/tech/cvs_card.html#init">CVS环境初始化</A>：CVS环境的搭建 管理员 
<LI><A href="http://www.chedong.com/tech/cvs_card.html#daily">CVS的日常使用</A>：日常开发中最常用的CVS命令， 开发人员 管理员 
<LI><A href="http://www.chedong.com/tech/cvs_card.html#branch">CVS的分支开发</A>：项目按照不同进度和目标并发进行 管理员 
<LI><A href="http://www.chedong.com/tech/cvs_card.html#ssh">CVS的用户认证</A>：通过SSH的远程用户认证，安全，简单 管理员 
<LI><A href="http://www.chedong.com/tech/cvs_card.html#cvsweb">CVSWEB</A>：CVS的WEB访问界面大大提高代码版本比较的效率 管理员 
<LI><A href="http://www.chedong.com/tech/cvs_card.html#tag">CVS TAG</A>：将$<SPAN style="FONT-WEIGHT: bold">Id</SPAN>$ 加入代码注释中，方便开发过程的跟踪开发人员 
<LI><A href="http://www.chedong.com/tech/cvs_card.html#vss">CVS vs VSS</A>: CVS和Virsual SourceSafe的比较 开发人员 管理员 
<LI><A href="http://www.chedong.com/tech/cvs_card.html#wincvs">WinCVS:</A> 通过SSH认证的WinCVS认证设置 
<LI><A href="http://www.chedong.com/tech/cvs_card.html#cvstrac">基于CVSTrac的小组开发环境搭建</A>：通过CVSTrac实现web界面的CVS用户管理,集成的BUG跟踪和WIKI交流 
<LI><A href="http://www.chedong.com/tech/cvs_card.html#auth">CVS中的用户权限管理</A>：基于系统用户的CVS权限管理和基于CVSROOT/passwd的虚拟用户管理 <BR></LI></OL>
<P>一个系统20%的功能往往能够满足80%的需求，CVS也不例外，以下是CVS最常用的功能，可能还不到它全部命令选项的20%，作为一般开发人员平时会用cvs update和cvs commit就够了，更多的需求在实际应用过程中自然会出现，不时回头看看相关文档经常有意外的收获。</P>
<P><BR></P>
<H2><A name=init>CVS环境初始化</A></H2>环境设置：指定CVS库的路径CVSROOT 
<P>tcsh <BR>setenv CVSROOT /path/to/cvsroot <BR>bash <BR>CVSROOT=/path/to/cvsroot ; export CVSROOT </P>
<P>后面还提到远程CVS服务器的设置： <BR>CVSROOT=:ext:$USER@test.server.address#port:/path/to/cvsroot CVS_RSH=ssh; export CVSROOT CVS_RSH <BR><BR>初始化：CVS版本库的初始化。 <BR>cvs init </P>
<P>一个项目的首次导入 <BR>cvs import -m "write some comments here" project_name vendor_tag release_tag <BR>执行后：会将所有源文件及目录导入到/path/to/cvsroot/project_name目录下 <BR><I>vender_tag: 开发商标记 <BR>release_tag: 版本发布标记</I> </P>
<P>项目导出：将代码从CVS库里导出 <BR>cvs checkout project_name <BR><I>cvs 将创建project_name目录，并将最新版本的源代码导出到相应目录中。这个checkout和Virvual SourceSafe中的check out不是一个概念，相对于Virvual SourceSafe的check out是cvs update， check in是cvs commit。</I> <BR><BR></P>
<H2><A style="FONT-WEIGHT: normal" name=daily>CVS的日常使用</A><B> </B></H2>
<P></P>
<P><B>注意：第一次导出以后，就不是通过cvs checkout来同步文件了，而是要进入刚才cvs checkout project_name导出的project_name目录下进行具体文件的版本同步（添加，修改，删除）操作。</B> </P>
<P><U>将文件同步到最新的版本 <BR></U>cvs update <BR><I>不制定文件名，cvs将同步所有子目录下的文件，也可以制定某个文件名/目录进行同步 <BR></I>cvs update file_name <BR><I>最好每天开始工作前或将自己的工作导入到CVS库里前都要做一次，并养成“先同步 后修改”的习惯，和Virvual SourceSafe不同，CVS里没有文件锁定的概念，所有的冲突是在commit之前解决，如果你修改过程中，有其他人修改并commit到了CVS 库中，CVS会通知你文件冲突，并自动将冲突部分用 <BR>&gt;&gt;&gt;&gt;&gt;&gt; <BR>content on cvs server <BR>&lt;&lt;&lt;&lt;&lt;&lt; <BR>content in your file <BR>&gt;&gt;&gt;&gt;&gt;&gt; <BR>标记出来，由你确认冲突内容的取舍。 <BR>版本冲突一般是在多个人修改一个文件造成的，但这种项目管理上的问题不应该指望由CVS来解决。</I> </P>
<P><U>确认修改写入到CVS库里</U> <BR>cvs commit -m "write some comments here" file_name </P>
<P><I>注意：CVS的很多动作都是通过cvs commit进行最后确认并修改的，最好每次只修改一个文件。在确认的前，还需要用户填写修改注释，以帮助其他开发人员了解修改的原因。如果不用写-m "comments"而直接确认`cvs commit file_name` 的话，cvs会自动调用系统缺省的文字编辑器(一般是vi)要求你写入注释。 <BR>注释的质量很重要：所以不仅必须要写，而且必须写一些比较有意义的内容：以方便其他开发人员能够很好的理解 <BR>不好的注释，很难让其他的开发人员快速的理解：比如： -m "bug fixed" 甚至 -m "" <BR>好的注释，甚至可以用中文: -m "在用户注册过程中加入了Email地址校验"</I> <BR><BR>修改某个版本注释：每次只确认一个文件到CVS库里是一个很好的习惯，但难免有时候忘了指定文件名，把多个文件以同样注释commit到CVS库里了，以下命令可以允许你修改某个文件某个版本的注释： <BR>cvs admin -m 1.3:"write some comments here" file_name <BR><BR><U>添加文件</U> <BR>创建好新文件后，比如：touch new_file <BR>cvs add new_file <BR><I>注意：对于图片，Word文档等非纯文本的项目，需要使用cvs add -kb选项按2进制文件方式导入(k表示扩展选项，b表示binary)，否则有可能出现文件被破坏的情况 <BR>比如： <BR>cvs add -kb new_file.gif <BR>cvs add -kb readme.doc</I> </P>
<P><I>如果关键词替换属性在首次导入时设置错了怎么办？ <BR></I>cvs admin -kkv new_file.css <BR><I><BR></I><SPAN style="TEXT-DECORATION: underline">然后确认修改并注释</SPAN> <BR>cvs ci -m "write some comments here" </P>
<P><U>删除文件</U> <BR>将某个源文件物理删除后，比如：rm file_name <BR>cvs rm file_name <BR>然后确认修改并注释 <BR>cvs ci -m "write some comments here" <BR>以上面前2步合并的方法为： <BR>cvs rm -f file_name <BR>cvs ci -m "why delete file" <BR><I>注意：很多cvs命令都有缩写形式：commit=&gt;ci; update=&gt;up; checkout=&gt;co/get; remove=&gt;rm;</I> </P>
<P><U>添加目录</U> <BR>cvs add dir_name <BR><BR><U>查看修改历史</U> <BR>cvs log file_name <BR>cvs history file_name <BR><BR><U>查看当前文件不同版本的区别</U> <BR>cvs diff -r1.3 -r1.5 file_name <BR>查看当前文件（可能已经修改了）和库中相应文件的区别 <BR>cvs diff file_name <BR>cvs的web界面提供了更方便的定位文件修改和比较版本区别的方法，具体安装设置请看后面的cvsweb使用 </P>
<P><U>正确的通过CVS恢复旧版本的方法</U>： <BR>如果用cvs update -r1.2 file.name <BR>这个命令是给file.name加一个STICK TAG： "1.2" ，虽然你的本意只是想将它恢复到1.2版本 <BR>正确的恢复版本的方法是：cvs update -p -r1.2 file_name &gt;file_name <BR>如果不小心已经加成STICK TAG的话：用cvs update -A 解决 </P>
<P><U>移动文件/文件重命名</U> <BR>cvs里没有cvs move或cvs rename，因为这两个操作是可以由先cvs remove old_file_name，然后cvs add new_file_name实现的。 </P>
<P><U>删除/移动目录</U> <BR>最方便的方法是让管理员直接移动，删除CVSROOT里相应目录（因为CVS一个项目下的子目录都是独立的，移动到$CVSROOT目录下都可以作为新的独立项目：好比一颗树，其实砍下任意一枝都能独立存活），对目录进行了修改后，要求其开发人员重新导出项目cvs checkout project_name 或者用cvs update -dP同步。 </P>
<P><U>项目发布导出不带CVS目录的源文件</U> <BR>做开发的时候你可能注意到了，每个开发目录下，CVS都创建了一个CVS/目录。里面有文件用于记录当前目录和CVS库之间的对应信息。但项目发布的时候你一般不希望把文件目录还带着含有CVS信息的CVS目录吧，这个一次性的导出过程使用cvs export命令，不过export只能针对一个TAG或者日期导出，比如： <BR>cvs export -r release1 project_name <BR>cvs export -D 20021023 project_name <BR>cvs export -D now project_name </P>
<H2><A name=branch>CVS Branch：项目多分支同步开发</A></H2>确认版本里程碑：多个文件各自版本号不一样，项目到一定阶段，可以给所有文件统一指定一个阶段里程碑版本号，方便以后按照这个阶段里程碑版本号导出项目，同时也是项目的多个分支开发的基础。 <BR>
<P>cvs tag release_1_0</P>
<P><U>开始一个新的里程碑</U>： <BR>cvs commit -r 2 标记所有文件开始进入2.x的开发 </P>
<P><I>注意：CVS里的revsion和软件包的发布版本可以没有直接的关系。但所有文件使用和发布版本一致的版本号比较有助于维护。</I> </P>
<P><U>版本分支的建立</U> <BR>在开发项目的2.x版本的时候发现1.x有问题，但2.x又不敢用，则从先前标记的里程碑：release_1_0导出一个分支 release_1_0_patch <BR>cvs rtag -b -r release_1_0 release_1_0_patch proj_dir </P>
<P>一些人先在另外一个目录下导出release_1_0_patch这个分支：解决1.0中的紧急问题， <BR>cvs checkout -r release_1_0_patch <BR>而其他人员仍旧在项目的主干分支2.x上开发 </P>
<P>在release_1_0_patch上修正错误后，标记一个1.0的错误修正版本号 <BR>cvs tag release_1_0_patch_1 </P>
<P>如果2.0认为这些错误修改在2.0里也需要，也可以在2.0的开发目录下合并release_1_0_patch_1中的修改到当前代码中： <BR>cvs update -j release_1_0_patch_1 </P>
<H2><A name=ssh>CVS的远程认证通过SSH远程访问CVS</A></H2>使用cvs本身基于pserver的远程认证很麻烦,需要定义服务器和用户组，用户名，设置密码等， <BR>
<P>常见的登陆格式如下： <BR>cvs -d :pserver:cvs_user_name@cvs.server.address:/path/to/cvsroot login <BR>例子： <BR>cvs -d :pserver:cvs@samba.org:/cvsroot login </P>
<P>不是很安全，因此一般是作为匿名只读CVS访问的方式。从安全考虑，通过系统本地帐号认证并通过SSH传输是比较好的办法，通过在客户机的 /etc/profile里设置一下内容： <BR>CVSROOT=:ext:$USER@cvs.server.address#port:/path/to/cvsroot CVS_RSH=ssh; export CVSROOT CVS_RSH <BR>所有客户机所有本地用户都可以映射到CVS服务器相应同名帐号了。 </P>
<P>比如:</P>
<P>CVS服务器是192.168.0.3，上面CVSROOT路径是/home/cvsroot，另外一台开发客户机是192.168.0.4，如果 tom在2台机器上都有同名的帐号，那么从192.168.0.4上设置了： <BR>export CVSROOT=:ext:tom@192.168.0.3:/home/cvsroot <BR>export CVS_RSH=ssh <BR>tom就可以直接在192.168.0.4上对192.168.0.3的cvsroot进行访问了（如果有权限的话） <BR>cvs checkout project_name <BR>cd project_name <BR>cvs update <BR>... <BR>cvs commit <BR></P>
<P>如果CVS所在服务器的SSH端口不在缺省的22，或者和客户端与CVS服务器端SSH缺省端口不一致，有时候设置了： <BR>:ext:$USER@test.server.address#port:/path/to/cvsroot <BR><BR>仍然不行，比如有以下错误信息： <BR>ssh: test.server.address#port: Name or service not known <BR>cvs [checkout aborted]: end of file from server (consult above messages if any) <BR><BR>解决的方法是做一个脚本指定端口转向（不能使用alias，会出找不到文件错误）： <BR>创建一个/usr/bin/ssh_cvs文件，假设远程服务器的SSH端口是非缺省端口：34567 <BR>#!/bin/sh <BR>/usr/bin/ssh -p 34567 "$@" <BR>然后：chmod +x /usr/bin/ssh_cvs <BR>并CVS_RSH=ssh_cvs; export CVS_RSH </P>
<P>注意：port是指相应服务器SSH的端口，不是指cvs专用的pserver的端口 <BR><BR></P>
<H2><A name=cvsweb>CVSWEB：提高文件浏览效率</A></H2>CVSWEB就是CVS的WEB界面，可以大大提高程序员定位修改的效率: <BR>
<P>使用的样例可以看：<A href="http://www.freebsd.org/cgi/cvsweb.cgi">http://www.freebsd.org/cgi/cvsweb.cgi</A> </P>
<P>CVSWEB的下载：CVSWEB从最初的版本已经演化出很多功能界面更丰富的版本，这个是我个人感觉安装设置比较方便的： <BR>原先在：<S>http://www.spaghetti-code.de/software/linux/cvsweb/</S>，但目前已经删除，<A href="http://www.chedong.com/tech/cvsweb.tgz">目前仍可以在本站下载CVSWEB</A>，其实最近2年<A href="http://www.freebsd.org/projects/cvsweb.html">FreeBSD的CVSWeb项目</A>已经有了更好的发展吧，而当初没有用FreeBSD那个版本主要就是因为没有彩色的文件Diff功能。 <BR>下载解包： <BR>tar zxf cvsweb.tgz <BR>把配置文件cvsweb.conf放到安全的地方（比如和apache的配置放在同一个目录下）， <BR>修改：cvsweb.cgi让CGI找到配置文件： <BR>$config = $ENV{'CVSWEB_CONFIG'} || '/path/to/apache/conf/cvsweb.conf'; <BR><BR>转到/path/to/apache/conf下并修改cvsweb.conf： </P>
<OL>
<LI>修改CVSROOT路径设置： <BR>%CVSROOT = ( <BR>'Development' =&gt; '/path/to/cvsroot', #&lt;==修改指向本地的CVSROOT <BR>); 
<LI>缺省不显示已经删除的文档： <BR>"hideattic" =&gt; "1",#&lt;==缺省不显示已经删除的文档 
<LI>在配置文件cvsweb.conf中还可以定制页头的描述信息，你可以修改$long_intro成你需要的文字 </LI></OL>
<P>CVSWEB可不能随便开放给所有用户，因此需要使用WEB用户认证： <BR>先生成 passwd: <BR>/path/to/apache/bin/htpasswd -c cvsweb.passwd user <BR><BR>修改httpd.conf: 增加 <BR>&lt;Directory "/path/to/apache/cgi-bin/cvsweb/"&gt; <BR>AuthName "CVS Authorization" <BR>AuthType Basic <BR>AuthUserFile /path/to/cvsweb.passwd <BR>require valid-user <BR>&lt;/Directory&gt; <BR><BR></P>
<H2><A name=tag>CVS TAGS: $Id: cvs_card.html,v 1.5 2003/03/09 08:41:46 chedong Exp $</A></H2>将$Id: cvs_card.html,v 1.9 2003/11/09 07:57:11 chedong Exp $ 加在程序文件开头的注释里是一个很好的习惯，cvs能够自动解释更新其中的内容成：file_name version time user_name 的格式，比如：cvs_card.txt,v 1.1 2002/04/05 04:24:12 chedong Exp，可以这些信息了解文件的最后修改人和修改时间 <BR>
<P><BR></P><PRE>几个常用的缺省文件：
default.php
&lt;?php
/*
 * Copyright (c) 2002 Company Name.
 * $Header: /home/cvsroot/tech/cvs_card.html,v 1.9 2003/11/09 07:57:11 chedong Exp $
 */

?&gt;
====================================
Default.java: 注意文件头一般注释用 /* 开始 JAVADOC注释用 /** 开始的区别
/*
 * Copyright (c) 2002 MyCompany Name.
 * $Header: /home/cvsroot/tech/cvs_card.html,v 1.9 2003/11/09 07:57:11 chedong Exp $
 */

package com.mycompany;

import java.;

/**
 * comments here
 */
public class Default {
    /**
     * Comments here
     * @param
     * @return
     */
    public toString() {

    }
}
====================================
default.pl:
#!/usr/bin/perl -w
# Copyright (c) 2002 Company Name.
# $Header: /home/cvsroot/tech/cvs_card.html,v 1.9 2003/11/09 07:57:11 chedong Exp $

# file comments here

use strict;

</PRE>
<H2><A name=vss>CVS vs VSS</A></H2>
<P>CVS没有文件锁定模式，VSS在check out同时，同时记录了文件被导出者锁定。 </P>
<P>CVS的update和commit， VSS是get_lastest_version和check in </P>
<P>对应VSS的check out/undo check out的CVS里是edit和unedit </P>
<P>在CVS中，标记自动更新功能缺省是打开的，这样也带来一个潜在的问题，就是不用-kb方式添加binary文件的话在cvs自动更新时可能会导致文件失效。</P>
<P>$Header: /home/cvsroot/tech/cvs_card.html,v 1.5 2003/03/09 08:41:46 chedong Exp $ $Date: 2003/11/09 07:57:11 $这样的标记在Virsual SourceSafe中称之为Keyword Explaination，缺省是关闭的，需要通过OPITION打开，并指定需要进行源文件关键词扫描的文件类型：*.txt,*.java, *.html...</P>
<P>对于Virsual SourceSafe和CVS都通用的TAG有： <BR>$Header: /home/cvsroot/tech/cvs_card.html,v 1.5 2003/03/09 08:41:46 chedong Exp $ <BR>$Author: chedong $ <BR>$Date: 2003/11/09 07:57:11 $ <BR>$Revision: 1.9 $ </P>
<P>我建议尽量使用通用的关键词保证代码在CVS和VSS都能方便的跟踪。 </P>
<H2><A name=wincvs>WinCVS</A></H2>下载： <BR>
<P>cvs Windows客户端：目前稳定版本为1.2 <BR><A href="http://cvsgui.sourceforge.net/">http://cvsgui.sourceforge.net</A> <BR>ssh Windows客户端 <BR><A href="http://www.networksimplicity.com/openssh/">http://www.networksimplicity.com/openssh/</A> <BR><BR>安装好以上2个软件以后： <BR>WinCVS客户端的admin==&gt;preference设置 <BR>1 在general选单里 <BR>设置CVSROOT： username@192.168.0.123:/home/cvsroot <BR>设置Authorization: 选择SSH server <BR><BR>2 Port选单里 <BR>钩上：check for alternate rsh name <BR>并设置ssh.exe的路径，缺省是装在 C:\Program Files\NetworkSimplicity\ssh\ssh.exe </P>
<P>然后就可以使用WinCVS进行cvs操作了，所有操作都会跳出命令行窗口要求你输入服务器端的认证密码。 </P>
<P>当然，如果你觉得这样很烦的话，还有一个办法就是生成一个没有密码的公钥/私钥对，并设置CVS使用基于公钥/私钥的SSH认证（在general 选单里）。</P>
<P>可以选择的diff工具：examdiff <BR>下载： <BR><A href="http://www.prestosoft.com/examdiff/examdiff.htm">http://www.prestosoft.com/examdiff/examdiff.htm</A> <BR>还是在WinCVS菜单admin==&gt;preference的WinCVS选单里 <BR>选上：Externel diff program <BR>并设置diff工具的路径，比如：C:\Program Files\ed16i\ExamDiff.exe <BR>在对文件进行版本diff时，第一次需要将窗口右下角的use externel diff选上。 </P>
<H2><A name=cvstrac>基于CVSTrac的小组开发环境搭建</A></H2>作为一个小组级的开发环境，版本控制系统和BUG跟踪系统等都涉及到用户认证部分。如何方便的将这些系统集成起来是一个非常困难的事情，毕竟我们不能指望 Linux下有像Source Offsite那样集成度很高的版本控制/BUG跟踪集成系统。 <BR><BR>我个人是很反对使用pserver模式的远程用户认证的，但如果大部分组员使用WINDOWS客户端进行开发的话，总体来说使用 CVSROOT/passwd认证还是很难避免的，但CVS本身用户的管理比较麻烦。本来我打算自己用perl写一个管理界面的，直到我发现了 CVSTrac：一个基于WEB界面的BUG跟踪系统，它外挂在CVS系统上的BUG跟踪系统，其中就包括了WEB界面的CVSROOT/passwd文件的管理，甚至还集成了WIKIWIKI讨论组功能。 
<P>这里首先说一下CVS的pserver模式下的用户认证，CVS的用户认证服务是基于inetd中的： <BR>cvspserver stream tcp nowait apache /usr/bin/cvs cvs --allow-root=/home/cvsroot pserver <BR>一般在2401端口（这个端口号很好记：49的平方） <BR><BR>CVS用户数据库是基于CVSROOT/passwd文件，文件格式： <BR>[username]:[crypt_password]:[mapping_system_user] <BR>由于密码都用的是UNIX标准的CRYPT加密，这个passwd文件的格式基本上是apache的htpasswd格式的扩展（比APACHE的 PASSWD文件多一个系统用户映射字段），所以这个文件最简单的方法可以用 <BR>apache/bin/htpasswd -b myname mypassword <BR>创建。注意：通过htpasswd创建出来的文件会没有映射系统用户的字段 <BR>例如： <BR>new:geBvosup/zKl2 <BR>setup:aISQuNAAoY3qw <BR>test:hwEpz/BX.rEDU </P>
<P>映射系统用户的目的在于：你可以创建一个专门的CVS服务帐号，比如用apache的运行用户apache，并将/home/cvsroot目录下的所有权限赋予这个用户，然后在passwd文件里创建不同的开发用户帐号，但开发用户帐号最后的文件读写权限都映射为apache用户，在SSH模式下多个系统开发用户需要在同一个组中才可以相互读写CVS库中的文件。</P>
<P>进一步的，你可以将用户分别映射到apache这个系统用户上。 <BR>new:geBvosup/zKl2:apache <BR>setup:aISQuNAAoY3qw:apache <BR>test:hwEpz/BX.rEDU:apache </P>
<P>CVSTrac很好的解决了CVSROOT/passwd的管理问题，而且包含了BUG跟踪报告系统和集成WIKIWIKI交流功能等，使用的 CGI方式的安装，并且基于<A href="http://www.gnu.org/copyleft/gpl.html">GNU Public License</A>： <BR></P>
<P align=left>在inetd里加入cvspserver服务： <BR>cvspserver stream tcp nowait apache /usr/bin/cvs cvs --allow-root=/home/cvsroot pserver </P>
<P align=left>xietd的配置文件：%cat cvspserver <BR>service cvspserver <BR>{ <BR>disable = no <BR>socket_type = stream <BR>wait = no <BR>user = apache <BR>server = /usr/bin/cvs <BR>server_args = -f --allow-root=/home/cvsroot pserver <BR>log_on_failure += USERID <BR>} </P>
<P>注意：这里的用户设置成apache目的是和/home/cvsroot的所有用户一致，并且必须让这个这个用户对/home/cvsroot/下的 CVSROOT/passwd和cvstrac初始化生成的myproj.db有读取权限。</P>
<P></P>
<P>安装过程 </P>
<OL>
<LI>下载：可以从<A href="http://www.cvstrac.org/">http://www.cvstrac.org</A> 下载 <BR>我用的是已经在Linux上编译好的应用程序包：cvstrac-1.1.2.bin.gz， <BR>%gzip -d cvstrac-1.1.2.bin.gz <BR>%chmod +x cvstrac-1.1.2.bin <BR>#mv cvstarc-1.1.1.bin /usr/bin/cvstrac <BR>如果是从源代码编译： <BR>从 http://www.sqlite.org/download.html 下载SQLITE的rpm包： <BR>rpm -i sqlite-devel-2.8.6-1.i386.rpm <BR>从 ftp://ftp.cvstrac.org/cvstrac/ 下载软件包 <BR>解包，假设解包到/home/chedong/cvstrac-1.1.2下，并规划将cvstrac安装到/usr/local/bin目录下， cd /home/chedong/cvstrac-1.1.2 编辑linux-gcc.mk: <BR>修改： <BR>SRCDIR = /home/chedong/cvstrac-1.1.2 <BR>INSTALLDIR = /usr/local/bin <BR>然后 <BR>mv linux-gcc.mk Makefile <BR>make <BR>#make install <BR><BR>
<LI>初始化cvstrac数据库：假设数据库名是 myproj <BR>在已经装好的CVS服务器上（CVS库这时候应该已经是初始化好了，比如：cvs init初始化在/home/cvsroot里），运行一下 <BR>%cvstrac init /home/cvsroot myproj <BR>运行后，/home/cvsroot里会有一个的myproj.db库，使用CVSTRAC服务，/home/cvsroot/myproj.db /home/cvsroot/CVSROOT/readers /home/cvsroot/CVSROOT/writers /home/cvsroot/CVSROOT/passwd这几个文件对于web服务的运行用户应该是可写的，在RedHat8上，缺省就有一个叫 apache用户和一个apache组，所以在httpd.conf文件中设置了用apache用户运行web服务： <BR>User apache <BR>Group apache， <BR>然后设置属于apache用户和apache组 <BR>#chown -R apache:apache /home/cvsroot <BR>-rw-r--r-- 1 apache apache 55296 Jan 5 19:40 myproj.db <BR>drwxrwxr-x 3 apache apache 4096 Oct 24 13:04 CVSROOT/ <BR>drwxrwxr-x 2 apache apache 4096 Aug 30 19:47 some_proj/ <BR>此外还在/home/cvsroot/CVSROOT中设置了： <BR>chmod 664 readers writers passwd <BR>
<LI>在apche/cgi-bin目录中创建脚本cvstrac: <BR>#!/bin/sh <BR>/usr/bin/cvstrac cgi /home/cvsroot <BR>设置脚本可执行： <BR>chmod +x /home/apache/cgi-bin/cvstrac <BR>
<LI>从 http://cvs.server.address/cgi-bin/cvstrac/myproj 进入管理界面 <BR>缺省登录名：setup 密码 setup <BR>对于一般用户可以从： <BR>http://cvs.server.address/cgi-bin/cvstrac/myproj 
<LI>在setup中重新设置了CVSROOT的路径后，/home/cvsroot <BR>如果是初次使用需要在/home/cvsroot/CVSROOT下创建passwd, readers, writers文件 <BR>touch passwd readers writers <BR>然后设置属于apache用户， <BR>chown apache.apache passwd readers writers <BR>这样使用setup用户创建新用户后会同步更新CVSROOT/passwd下的帐号 <BR></LI></OL>
<P align=left>修改登录密码，进行BUG报告等， <BR>更多使用细节可以在使用中慢慢了解。 <BR></P>
<P align=left>对于前面提到的WinCVS在perference里设置： <BR>CVSROOT栏输入：username@ip.address.of.cvs:/home/cvsroot <BR>Authenitication选择：use passwd file on server side <BR>就可以了从服务器上进行CVS操作了。 <BR></P>
<H2><A name=auth>CVS的用户权限管理</A></H2>
<P align=left>CVS的权限管理分2种策略： <BR></P>
<UL>
<LI>基于系统文件权限的系统用户管理：适合多个在Linux上使用系统帐号的开发人员进行开发。 
<LI>基于CVSROOT/passwd的虚拟用户管理：适合多个在Windows平台上的开发人员将帐号映射成系统帐号使用。 </LI></UL>为什么使用apache/apache用户？首先RedHat8中缺省就有了，而且使用这个用户可以方便通过cvstrac进行WEB管理。 <BR>chown -R apache.apache /home/cvsroot <BR>chmod 775 /home/cvsroot <BR>
<P align=left>Linux上通过ssh连接CVS服务器的多个开发人员：通过都属于apache组实现文件的共享读写 <BR>开发人员有开发服务器上的系统帐号：sysuser1 sysuser2，设置让他们都属于apache组，因为通过cvs新导入的项目都是对组开放的：664权限的，这样无论那个系统用户导入的项目文件，只要文件的组宿主是apache，所有其他同组系统开发用户就都可以读写；基于ssh远程认证的也是一样。 <BR></P>
<P align=left>&nbsp; &nbsp;apache(system group) <BR>/ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \ <BR>sysuser1 &nbsp; sysuser2 &nbsp; &nbsp; sysuser3 <BR></P>
<P align=left>Windows上通过cvspserver连接CVS服务器的多个开发人员：通过在passwd文件种映射成 apache用户实现文件的共享读写 <BR>他们的帐号通过CVSROOT/passwd和readers writers这几个文件管理；通过cvstrac设置所有虚拟用户都映射到apache用户上即可。 <BR></P>
<P align=left>&nbsp; &nbsp;apache(system user) <BR>/ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\ <BR>windev1 &nbsp; &nbsp; windev2 &nbsp; &nbsp; &nbsp;windev3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </P>
<P align=left></P>
<P></P>
<P>利用cvs + (WinCVS/cvsweb/cvstrac)，构成了一个相对完善的跨平台工作组开发版本控制环境。</P>
<P>相关资源： </P>
<P>CVS HOME： <BR><A href="http://www.cvshome.org/">http://www.cvshome.org</A> </P>
<P>CVS FAQ： <BR><A href="http://www.loria.fr/~molli/cvs-index.html">http://www.loria.fr/~molli/cvs-index.html</A> <BR><BR>相关网站: <BR><A href="http://directory.google.com/Top/Computers/Software/Configuration_Management/Tools/Concurrent_Versions_System/">http://directory.google.com/Top/Computers/Software/Configuration_Management/Tools/Concurrent_Versions_System/</A> <BR></P>
<P>CVS--并行版本系统 <BR><A href="http://www.soforge.com/cvsdoc/zh_CN/book1.html">http://www.soforge.com/cvsdoc/zh_CN/book1.html</A> </P>
<P>CVS 免费书: <BR><A href="http://cvsbook.red-bean.com/">http://cvsbook.red-bean.com/</A> </P>
<P>CVS 命令的速查卡片： <BR><A href="http://www.refcards.com/about/cvs.html">http://www.refcards.com/about/cvs.html</A> </P>
<P>WinCVS: <BR><A href="http://cvsgui.sourceforge.net/">http://cvsgui.sourceforge.net/</A> </P>
<P>CVSTrac: A Web-Based Bug And Patch-Set Tracking System For CVS <BR><A href="http://www.cvstrac.org/">http://www.cvstrac.org</A> </P>
<P>StatCVS：基于CVS的代码统计工具：按代码量，按开发者的统计表等 <BR><A href="http://sourceforge.net/projects/statcvs">http://sourceforge.net/projects/statcvs <BR></A></P>如何在WEB开发中规划CVS上：在Google上查 "cvs web development" <BR><A href="http://ccm.redhat.com/bboard-archive/cvs_for_web_development/index.html">http://ccm.redhat.com/bboard-archive/cvs_for_web_development/index.html</A> <BR><BR>一些集成了CVS的IDE环境： <BR><A href="http://www.eclipse.org/">Eclipse</A> <BR><A href="http://www.magicunix.com/product_ch.html">Magic C++</A> <BR><img src ="http://www.blogjava.net/qq13367612/aggbug/16666.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-24 22:23 <a href="http://www.blogjava.net/qq13367612/articles/16666.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>怎么做需求分析</title><link>http://www.blogjava.net/qq13367612/articles/16020.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Fri, 14 Oct 2005 14:29:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/16020.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/16020.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/16020.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/16020.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/16020.html</trackback:ping><description><![CDATA[<P>在具体的研究需求分析之前，我们先了解一下软件工程这个概念。软件工程分为三个层次，过程层、方法层、工具层。在最基础的过程层，最重要的就是一组被称为关键过程区域（KPAs）的框架（KPA的概念在讨论CMM的书中有详细的概念说明）。关键过程区域构成了软件项目的管理控制的基础，并且确立了上下文各区域的关系，其中规定了技术方法的采用、工程产品的，模型、文档、数据、报告、表格等，等的产生、里程碑的建立、质量的保证及变化的适当管理。方法层主要是过程在技术上的实现。它解决的问题是如何做。软件工程方法涵盖了一系列的任务：需求分析、设计、编程、测试、维护。同时他还包括了一组基本原则，控制了每一个的关键过程区域。工具层就很好理解了，他对过程层和方法层提供了自动和半自动的支持。这些辅助工具就称为CASE。<BR>　　可以看到需求分析的位置，但是事实上需求分析是跨越了软件工程的三个层次的。这一点是和其他的过程是一样的。当然我们这里比较重点强调的是在软件工程的方法层，同时也涉及到一些过程层的思想，至于工具层则不再我们的讨论之列，但是会提到一些很适合在需求分析时应用的工具，诸如Word、Excel、Visio等。<BR><FONT color=#ff0000>方法</FONT><BR>　　需求分析都包括了哪些方法呢？这里列举出在《需求分析》一书中推荐的一些方法，<BR>　　1) 绘制系统关联图，这种关联图是用于定义系统与系统外部实体间的界限和接口的简单模型。同时它也明确了通过接口的信息流和物质流。<BR>　　2) 创建用户接口原型，当开发人员或用户不能确定需求时，开发一个用户接口原型—一个可能的局部实现—这样使得许多概念和可能发生的事更为直观明了。用户通过评价原型将使项目参与者能更好地相互理解所要解决的问题。注意要找出需求文档与原型之间所有的冲突之处。<BR>　　3) 分析需求可行性，在允许的成本、性能要求下，分析每项需求实施的可行性，明确与每项需求实现相联系的风险，包括与其它需求的冲突，对外界因素的依赖和技术障碍。 　　4) 确定需求的优先级别，应用分析方法来确定使用实例、产品特性或单项需求实现的优先级别。以优先级为基础确定产品版本将包括哪些特性或哪类需求。当允许需求变更时，在特定的版本中加入每一项变更，并在那个版本计划中作出需要的变更。<BR>　　5) 为需求建立模型，需求的图形分析模型是软件需求规格说明极好的补充说明。它们能提供不同的信息与关系以有助于找到不正确的、不一致的、遗漏的和冗余的需求。这样的模型包括数据流图、实体关系图、状态变换图、对话框图、对象类及交互作用图。<BR>　　6) 创建数据字典，数据字典是对系统用到的所有数据项和结构的定义，以确保开发人员使用统一的数据定义。在需求阶段，数据字典至少应定义客户数据项以确保客户与开发小组是使用一致的定义和术语。分析和设计工具通常包括数据字典组件。<BR>　　7) 使用质量功能调配，（QFD）是一种高级系统技术，它将产品特性、属性与对客户的重要性联系起来。该技术提供了一种分析方法以明确那些是客户最为关注的特性。QFD将需求分为三类：期望需求，即客户或许并未提及，但如若缺少会让他们感到不满意；普通需求；兴奋需求，即实现了会给客户带去惊喜，但若未实现也不会受到责备（Zultner 1993;Pardee 1996）。<BR>　　记住一点，不要试图在你的项目中把这些方法都用上去，四个现代化并不是一夜就可以实现的。同样，尝试着使用你认为对你很有帮助的方法，确实收到效果之后，在考虑继续学习方法。因为上面提到的都是需求分析的大方法，事实上还有很多很多的方法可以采用，例如，采用SRS模板、指明需求的来源、为每项需求注上标号、记录业务规范、创建需求跟踪能力矩阵、审查需求文档、以需求为依据编写测试用例、编写用户手册、确定合格的标准。<BR><FONT color=#ff0000>业务建模</FONT><BR>　　很多人都没有意识到业务需求阶段应该做些什么事情，实际上业务建模是最重要的一件事情。不要觉得业务建模这个词很深奥，让人模不着头脑。其实所有做过需求分析的人都做过业务建模，比如你了解企业的运作模式就?是一种你脑海中的业务建模。但是大多数人都没有科学的、系统的、文档化的做过业务建模。<BR>　　业务建模的目的在于： <BR>　　了解目标组织（将要在其中部署系统的组织）的结构及机制。<BR>　　了解目标组织中当前存在的问题并确定改进的可能性。<BR>　　确保客户、最终用户和开发人员就目标组织达成共识。<BR>　　导出支持目标组织所需的业务需求。<BR>　　上面的话是不是很抽象呢，其实没有什么复杂的：人和电脑是完全不同的思想（思维方式）。所以，原先适合人的业务流程对于计算机来说可不一定合适的，为了最大限度的利用计算机，必须要了解原先的业务流程并对此加易改造（流程自动化），当然这些动作需要得到用户的许可。有些人认为说只有ERP这种大系统才需要对业务流程进行重组，但是实际上，不论是部门级的MIS系统，还是社会级的电子商务系统，都需要对业务流程进行改造，所不同的只是改造的程度。<BR>　　业务建模很重要的一点是在分析企业流程的同时分析出基础企业对象（Common Business Object）（这个词我翻译的不好，如果大家有更好的翻译，请告诉我）。任何企业都有最基础的一些元素，例如银行的CBO就有帐户，制造业的CBO就有订单等。有一次我的一个在企业应用方面研究多年的朋友告诉我一个秘诀，他说，企业的CBO无非是4个：客户、员工、产品和供应商（银行的供应商应该称为同业）。其他的所有CBO都是在这四个CBO的基础上发展起来的。比如说CBO中客户和产品是多对多的关系，根据关系数据的理论，任何多对多的关系都可以拆分成多个一对多或一对一的关系。你就可以在这两个类之间引入订单类，客户和订单之间是一对多，订单和产品之间又是一对多，这样一个多对多的关系就拆分成两个一对多的关系，而新的订单类也就顺理成章的产生了。在订单类产生时，你可能还会加入一个关联类：业务员类。而业务员类又是从员工类继承下来的。所以呢，企业的四种CBO通过不同的组合，不同的关系，能够形成企业运作的许许多多的CBO。<BR>　　CBO是做业务建模的基础，在此基础上，通过评估业务状态，说明当前业务，确定业务流程，改进业务流程的定义，设计业务流程实现，改进角色和职责，研究流程自动化，开发领域模型等一系列在RUP中定义的工作流程实现业务建模的目标。<BR><FONT color=#ff0000>需求获取</FONT><BR>　　需求获取(requirement elicitation)是需求工程的主体。对于所建议的软件产品，获取需求是一个确定和理解不同用户类的需要和限制的过程。获取用户需求位于软件需求三个层次的中间一层。业务需求决定用户需求，它描述了用户利用系统需要完成的任务。从这些任务中，分析者能获得用于描述系统活动的特定的软件功能需求，这些系统活动有助于用户执行他们的任务。 需求获取是在问题及其最终解决方案之间架设桥梁的第一步。获取需求的一个必不可少的结果是对项目中描述的客户需求的普遍理解。一旦理解了需求，分析者、开发者和客户就能探索出描述这些需求的多种解决方案。参与需求获取者只有在他们理解了问题之后才能开始设计系统，否则，对需求定义的任何改进，设计上都必须大量的返工。把需求获取集中在用户任务上—而不是集中在用户接口上—有助于防止开发组由于草率处理设计问题而造成的失误。 需求获取、分析、编写需求规格说明和验证并不遵循线性的顺序，这些活动是相互隔开、增量和反复的。当你和客户合作时，你就将会问一些问题，并且取得他们所提供的信息（需求获取）。同时，你将处理这些信息以理解它们，并把它们分成不同的类别，还要把客户需求同可能的软件需求相联系（分析）。然后，你可以使客户信息结构化，并编写成文档和示意图（说明）。下一步，就可以让客户代表评审文档并纠正存在的错误（验证）。这四个过程贯穿着需求分析的整个阶段。 需求获取可能是软件开发中最困难、最关键、最易出错及最需要交流的方面。需求获取只有通过有效的客户—开发者的合作才能成功。分析者必须建立一个对问题进行彻底探讨的环境，而这些问题与产品有关。为了方便清晰地进行交流，就要列出重要的小组，而不是假想所有的参与者都持有相同的看法。对需求问题的全面考察需要一种技术，利用这种技术不但考虑了问题的功能需求方面，还可讨论项目的非功能需求。确定用户已经理解：对于某些功能的讨论并不意味着即将在产品中实现它。对于想到的需求必须集中处理并设定优先级?，以避免一个不能带来任何益处的无限大的项目。 需求获取是一个需要高度合作的活动，而并不是客户所说的需求的简单誊本。作为一个分析者，你必须透过客户所提出的表面需求理解他们的真正需求。询问一个可扩充（open-ended）的问题有助于你更好地理解用户目前的业务过程并且知道新系统如何帮助或改进他们的工作。调查用户任务可能遇到的变更，或者用户需要使用系统其它可能的方式。想像你自己在学习用户的工作，你需要完成什么任务？你有什么问题？从这一角度来指导需求的开发和利用。<BR>　　还有，探讨例外的情况：什么会妨碍用户顺利完成任务？对系统错误情况的反映，用户是如何想的？询问问题时，以“还有什么能” ,”当?时，将会发生什么”“你有没有曾经想过” ,“有没有人曾经”为开头。记下每一个需求的来源，这样向下跟踪直到发现特定的客户。<BR>　　有些时候，尝试着问一些“愚蠢”的问题也有助于客户打开话匣子。如果你直接要求客户写出业务是如何实现的，客户十有八九无法完成。但是如果你尝试着问一些实际的问题，例如：“以我的理解，你们收到订单后，会...”。客户立刻就会指出你的错误，并滔滔不绝的开始谈论业务，而你，就在一边仔细的聆听吧。这一招就叫做“抛砖引玉”。<BR>　　需求讨论会上必须要使用笔记本电脑，还要指定一个打字熟练的人把所有的讨论记录下来，记录的同时还要做一定的整理。如果不这样做，那么你结束会议的时候就会发现，所有的讨论只剩下一个模糊的印象，需求对你来说仍然是一件遥远的事情。在座谈讨论之后，记下所讨论的条目(item)，并请参与讨论的用户评论并更正。及早并经常进行座谈讨论是需求获取成功的一个关键途径，因为只有提供需求的人才能确定是否真正获取需求。进行深入收集和分析以消除任何冲突或不一致性。<BR>　　尽量把客户所持的假设解释清楚，特别是那些发生冲突的部分。从字里行间去理解以明确客户没有表达清楚但又想加入的特性或特征。Gause 和Weinberg（1989）提出使用“上下文无关问题”—这是一个高层次的问题，它可以获取业务问题和可能的解决方案的全部信息。客户对这些问题的回答诸如“产品要求怎样的精确度”或“你能帮我解释一下你为什么不同意某人的回答吗？”这些回答可以更直接地认识问题，而这是封闭（close-end）问题所不能做到的。<BR>　　需求获取利用了所有可用的信息来源，这些信息描述了问题域或在软件解决方案中合理的特性。一个研究表明：比起不成功的项目，一个成功的项目在开发者和客户之间采用了更多的交流方式（Kiel and Carmel 1995）。与单个客户或潜在的用户组一起座谈，对于业务软件包或信息管理系统（MIS）的应用来说是一种传统的需求来源。直接聘请用户进行获取需求的过程是为项目获得支持和买入（buy-in）的一种方式。<BR>　　尽量理解用户用于表述他们需求的思维过程。充分研究用户执行任务时作出决策的过程，并提取出潜在的逻辑关系。流程图和决策树是描述这些逻辑决策途径的好方法。<BR>　　在需求获取的过程中，你可能会发现对项目范围的定义存在误差，不是太大就是太小。如果范围太大，你将要收集比真正需要更多的需求，以传递足够的业务和客户的值，此时获取过程将会拖延。如果项目范围太小，那么客户将会提出很重要的但又在当前产品范围之外的需求。当前的范围太小，以致不能提供一个令人满意的产品。需求的获取将导致修改项目的范围和任务，但作出这样具有深远影响的改变，一定要小心谨慎。 正如经常所说的，需求主要是关于系统做什么，而解决方案如何实现是属于设计的范围。这样说虽然很简洁，但似乎过于简单化。需求的获取应该把重点放在“做什么”上，但在分析和设计之间还是存在一定的距离。你可以使用假设“怎么做”来分类并改善你对用户需求的理解。在需求的获取过程中，分析模型、屏幕图形和原型可以使概念表达得更加清楚，然后提供一个寻找错误和遗漏的办法。把你在需求开发阶段所形成的模型和屏幕效果看成是方便高效交流的概念性建议，而不应该看成是对设计者选择的一种限制。 需求获取讨论会中如果参与者过多，就会减慢进度。人数大致控制在5到7人是最好的。这些人包括客户、系统设计者、开发者和可视化设计者等主要工程角色。相反地，从极少的代表那里收集信息或者只听到呼声最高、最有舆论影响的用户的声音，也会造成问题。这将导致忽视特定用户类的重要的需求，或者其需求不能代表绝大多数用户的需要。最?好的权衡在于选择一些授权为他们的用户类发言的产品代表者，他们也被同组用户类的其它代表所支持。 没有一个简单、清楚的信号暗示你什么时候已完成需求获取。当客户和开发者与他们的同事聊天、阅读工业和商业上的文献及在早上沐浴时思考时，他们都将对潜在产品产生新的构思。你不可能全面收集需求，但是下列的提示将会暗示你在需求获取的过程中的返回点。<BR>　　1. 如果用户不能想出更多的使用实例，也许你就完成了收集需求的工作。用户总是按其重要性的顺序来确定使用实例的。<BR>　　2. 如果用户提出新的使用实例，但你可以从其它使用实例的相关功能需求中获得这些新的使用实例，这时也许你就完成了收集需求的工作。这些新的使用实例可能是你已获取的其它使用实例的可选过程。 　　3. 如果用户开始重复原先讨论过的问题，此时，也许你就完成了收集需求的工作。<BR>　　4. 如果所提出的新需求比你已确定的需求的优先级都低时，也许你就完成了收集需求的工作。<BR>　　5. 如果用户提出对将来产品的要求，而不是现在我们讨论的特定产品，也许你就完成了收集需求的工作。<BR>　　以上知识大致上讨论需求分析应该如何做，实际上对于需求分析的方法有很多很多，已经形成了一定的理论，当然这种理论比较偏向与方法学，而方法学的应用主要还是要靠个人。所以，大家在实际应用的时候，不妨结合自己的实际，有选择性的采用一些方法，那你就是成功的。 </P>
<P>多年来，分析者总是利用情节或经历来描述用户和软件系统的交互方式，从而获取需求（McGraw and Harbison 1997）。Ivar Jacobson（1992）把这种看法系统地阐述成用例（用例）的方法进行需求获取和建模。虽然用例来源于面向对象的开发环境，但是它也能应用在具有许多开发方法的项目中，因为用户并不关心你是怎样开发你的软件。而最重要的，用例的观点和思维过程带给需求开发的改变比起是否画正式的用例图显得更为重要。注意用户要利用系统做什么远远强于询问用户希望系统为他们做什么这一传统方法。 用例的重要功能是用画用例图的功能来鉴别和划分系统功能。它把系统分成角色（actor）和用例（用例）。角色(actor)表示系统用