mms://nv.sina.com.cn/bn/2006/06/28815307.wma
原版视频
[swf0=425,350]http://tv.mofile.com/cn/xplayer.swf?v=UWS6K7BF&p=http%3A%2F%2Fcache.mofile.com%2Ftv%2Fstatic%2Fu3%2FDisk1%2Fctc%2FUW%2FS6%2FUWS6K7BF.jpg&autoplay=0[/swf]
mms://nv.sina.com.cn/bn/2006/06/28815307.wma
原版视频
[swf0=425,350]http://tv.mofile.com/cn/xplayer.swf?v=UWS6K7BF&p=http%3A%2F%2Fcache.mofile.com%2Ftv%2Fstatic%2Fu3%2FDisk1%2Fctc%2FUW%2FS6%2FUWS6K7BF.jpg&autoplay=0[/swf]

下载地址 http://lib.verycd.com/2006/06/15/0000106934.html
最近有部新片《V字仇杀队》,imdb的评分高达8.3,而且是黑客帝国原班人马制作,如此一部电影怎能不看!
故事发生在未来的英国,一个被英国独裁政府用来做生物实验而变异的刺客V为了揭露英国政府的肮脏和卑劣;唤醒英国民众为了追求自由而反抗。最后V倒下了,但象征着极度独裁统治的英国议会大厦最终化为了烟花,千百万被V点化的英国民众用自己的力量证明了“People should not be afraid of their governments. Governments should be afraid of their people.”
“Remember, remember the 5th of November.”是影片中的经典台词。11月5日正是V变异和死亡的日子。其实整个故事情节都是基于1605年的盖伊·福克斯为推翻英王詹姆斯一世而策划炸毁国会大厦最终牺牲的真实历史。
这部电影让我想起了勇敢的心,为自由而战的信念超越了一切。然而在我们生活的世界中,“自由”也有游戏规则,“事实”不一定是真相。而像V一样的人也绝对不可能出现,但我们可以做到的是拥有追求真理的信念和为民族而战的勇气。
上一篇文章提到了我在开发显示Exchange未读邮件数的WebPart中遇到了身份凭据传递的问题。因为Exchange的WebDAV是根据不同的用户返回不同邮箱的数据,当然就是非匿名的。输入身份信息一种方法是在网页上放置一个输入用户名和密码的Form,这样构建的NetworkCredential不存在传递的问题。但是,由于我的网络是基于Windows域方式的,每个用户要登录到域中,因此使用Windows集成身份验证能够让用户在SharePoint中使用当前的身份凭据登录,这样比输入用户名密码更加方便和友好。也就是说,为了免去用户再次输入Exchange用户名和密码,需要把客户端当前登录的Credential(用户身份凭据)传递到Exchange服务器上。然而,我的Exchange服务器和SharePoint网站服务器是两台不同的服务器,如果要使用集成身份验证并使用Windows和SharePoint默认的NTLM身份验证协议是无法将当前HttpContext中的身份凭据从Web服务器传递到Exchange服务器上的。而且也不可能从当前的身份凭据中获得用户名和密码,所以也不可能自己构建一个可传递的NetworkCredential。这就是著名的“Double Hop”双跳问题。
当然解决这个问题有很多方法,比如可以用到SharePoint的单点登录Single-Sign-On(SSO)。但是每个用户需要在第一次使用之前先输入一次自己的Exchange密码储存到SSO数据库中,而且如果更改了Exchange密码需要再同时修改SSO数据,也比较麻烦。所以最好的解决方案就是使用Kerberos身份验证协议代替NTLM身份验证协议。
NTLM身份验证协议之所以无法传递身份凭据是由该协议本身的限制决定的,下图解释了原因。

其实说“身份凭据传递”是不太恰当的,实际上是让Web服务器账户模拟客户端的用户来再对Exchange服务器发送请求。从上图中我们可以看到NTLM协议无法让Web服务器模拟客户端,因此Exchange收到的是一个未知用户的请求,所以会返回401身份验证错误。
在这种情况下只能使用Kerberos协议,因为该协议最重要的特性之一就是可以委派。也就是说Web服务器可以模拟客户端对Exchange服务器发送请求。如下图所示。
另外,为了增加安全性,Windows Server 2003中还为Kerberos增加了约束委派特性。可以指定委派的服务,那么没有指定的服务将无法使用委派。如下图所示。
那么,如何启用Kerberos身份验证代替NTLM呢?步骤如下:
一、以SharePoint为例,首先要修改IIS的配置文件以启用Kerberos验证。
如果安装了SPS SP2以后则可以不用手动修改IIS配置文件,在SPS创建网站的时候就会有身份验证协议的选项。
二、为Web服务运行的帐号配置服务主体名称(SPN)
一般SPS的服务都是以一个域用户身份运行的,那么应该为该用户设置SPN。
三、为Web服务器运行的帐号配置委派信任关系
该步骤一定要设置为约束委派,我之前一直试验用非约束委派结果一直失败。
为SPS启用Kerberos身份验证的具体方法和说明可参考http://support.microsoft.com/default.aspx?scid=kb;zh-CN;832769
以上为我的案例中的步骤,不同情况配置情况不尽相同。在配置Kerberos委派的过程中有几个关键点。
1、IIS要设置为Windows集成验证
2、一定要确定客户端使用的是Kerberos身份验证协议,这个可以通过抓包软件或者Kerberos Tray来监视。注:Kerberos使用88端口。
3、如果Web服务是基于本地系统或者网络服务的则无需设置SPN,否则一定要为域用户设置SPN。
4、如果Web服务是基于本地系统或者网络服务的则要在Active Directory中为该Web服务的这台计算机设置委派信任关系,否则要为Web服务所基于的域用户设置委派信任关系,而且一定要设置成为约束委派!
5、Web.config中要有<authentication mode="Windows" />和<identity impersonate="true" />
更详细的信息、设置方法和故障排除方法可以参考http://www.microsoft.com/china/technet/prodtechnol/windowsserver2003/technologies/security/tkerbdel.mspx 。这篇文章虽然有点长不过可谓字字珠玑,我就是在认真研读后才最终解决我的问题的。

这两天为SharePoint开发了一个获取Exchange未读邮件数的WebPart。存取Exchange信息可以有很多种方法,象MAPI、CDO和WebDAV。我采用的就是WebDAV方法。WebDAV实际上是基于HTTP的一种协议,返回的标准XML数据。优点基于国际标准、方便远程应用、调试方便而且适用于任何程序语言,那缺点主要就是要自己处理返回的XML结果。
我的开发平台是.NET,主要的思路是使用System.Net.HttpWebRequest类来获取远程的WebDAV,然后分析返回的XML,提取出其中的“未读邮件”节点的数字。其中很重要的一点便是身份验证。因为Exchange的WebDAV是根据不同的用户返回不同邮箱的数据,当然就是非匿名的。因此,需要把客户端当前登录的Credential(用户身份凭据)传递到Exchange服务器上。然而我的Exchange服务器和SharePoint网站服务器是两台不同的服务器,如何才能把客户端的身份凭据通过Web服务器传递到Exchange服务器上呢?这个问题浪费了我不少时间才解决,我将再下一篇文章《使用Kerberos解决身份凭据传递问题》中详细介绍解决方法。
参考了Exchange SDK中的Sample,获取Exchange信息的主要代码如下:
private int GetUnReadMailCount()
{
string url=“http://mail.felixwoo.com/exchange/”; //指定Exchange服务器地址
System.Net.HttpWebRequest Request;
System.Net.WebResponse Response;
System.Net.CredentialCache MyCredentialCache;
string strUserName = “wuf”; //指定登录的用户名
string strRootURI = url+strUserName ; //得到要访问邮箱的WebDAV地址
string strPassword = “123456”; //指定该用户的密码
string strDomain = “felixwoo.com”; //指定域名
string strQuery ="";
byte[] bytes = null;
System.IO.Stream RequestStream = null;
System.IO.Stream ResponseStream = null;
XmlDocument ResponseXmlDoc = null;
XmlNodeList HrefNodes= null;
XmlNodeList SizeNodes= null;
int count=0;
try
{
// 用SQL查询WebDAV返回结果中的unreadcount节点.
strQuery = "<?xml version=\"1.0\"?><D:searchrequest xmlns:D = \"DAV:\" >"
+ "<D:sql>SELECT \"DAV:displayname\",\"urn:schemas:httpmail:unreadcount\" FROM \"" + strRootURI + "\""
+ "</D:sql></D:searchrequest>";
// 创建新的CredentialCache对象,构建身份凭据
MyCredentialCache = new System.Net.CredentialCache();
MyCredentialCache.Add( new System.Uri(strRootURI),
"NTLM",
new System.Net.NetworkCredential(strUserName, strPassword, strDomain)
);
// Create the HttpWebRequest object.
Request = (System.Net.HttpWebRequest)HttpWebRequest.Create(strRootURI);
// 指定HttpWebRequest的身份凭据,此处为关键所在。如果使用之前
// 创建的MyCredentialCache,则这个身份凭据是可以从Web服务器传递
// 到Exchange服务器的,但是这样带来的问题也很明显,就是不能够自
// 动获取当前登录到域的用户的身份。即便已经成功登录到域,那也只
// 能通过form再次输入用户名密码。因此,我在这里用的是
// Request.Credentials = CredentialCache.DefaultCredentials,
// 这样便可以获得当前用户的凭据,但是这样带来的问题便是上面提到的
// 身份凭据无法传递的问题,解决方法请关注下篇文章。
Request.Credentials = MyCredentialCache;
// 指定WebDAV的SEARCH方法
Request.Method = "SEARCH";
// Encode the body using UTF-8.
bytes = Encoding.UTF8.GetBytes((string)strQuery);
// Set the content header length. This must be
// done before writing data to the request stream.
Request.ContentLength = bytes.Length;
// Get a reference to the request stream.
RequestStream = Request.GetRequestStream();
// Write the SQL query to the request stream.
RequestStream.Write(bytes, 0, bytes.Length);
// Close the Stream object to release the connection
// for further use.
RequestStream.Close();
// Set the content type header.
Request.ContentType = "text/xml";
// Send the SEARCH method request and get the
// response from the server.
Response = (HttpWebResponse)Request.GetResponse();
// Get the XML response stream.
ResponseStream = Response.GetResponseStream();
// 创建XmlDocument对象,并获取收件箱的unreadcount节点的值
ResponseXmlDoc = new XmlDocument();
ResponseXmlDoc.Load(ResponseStream);
HrefNodes = ResponseXmlDoc.GetElementsByTagName("a:displayname");
SizeNodes = ResponseXmlDoc.GetElementsByTagName("d:unreadcount");
for(int i=0;i<HrefNodes.Count;i++)
{
if(HrefNodes[i].InnerText=="收件箱")
count=int.Parse(SizeNodes[i].InnerText);
}
ResponseStream.Close();
Response.Close();
}
catch(Exception)
{
// Catch any exceptions. Any error codes from the SEARCH
// method request on the server will be caught here, also.
return -1;
}
return count;
}
单位的门户网站构建于SharePoint,即时通讯平台是Live Communication Server(LCS)。由于LCS并不自带查询聊天记录的功能,所以为SharePoint开发了一个查询LCS聊天记录的WebPart。在此记录一下创建的过程。
一、创建前的准备
1、服务器端安装Sharepoint Portal Server
2、开发客户端安装Visual Studio .NET
3、安装WebPart模版Sharepoint Web Part Library Template for Visual Studio .NET
下载地址:http://www.microsoft.com/downloads/details.aspx?FamilyId=14D5D92F-C3A6-407C-AAD7-B8C41A4991BE&displaylang=en。在安装这个模版的时候需要指定Microsoft.SharePoint.dll的位置,需要从服务器上把该文件拷贝到开发端的本地。
二、开发步骤
1、首先创建查询LCS记录User Control。LCS的聊天记录保存在默认名为LcsLog的数据库中,其中会用到messages和users两张表,在messages中保存了聊天记录的内容,但是其中的发送和接受人都是以id形式表现,需要用此id再到users中查到相应的Email,最后再利用DirectoryService从Active Directory中获取对应的用户名称。最后保存为History.ascx。
2、创建 Web Control Library 项目,相关的引用和namespace等都会自动创建好。
3、在项目中通过“添加现有项…”菜单,将第一步中建立的UserControl的三个文件全部加入到此项目中。打开“History.ascx.cs”文件,将此文件第一行指定的namespace改成和此项目一致的“LCS”,打开“History.ascx”文件,将第一行的“<%@ Control>”标签中的“CodeBehind”属性删除,“Inherits”属性的值改为“LCS.History”。
4、转到步骤2创建的“WebPart1.cs”文件,定义一个用来保存UserControl的对象:private System.Web.UI.Control _innerControl; 然后重载CreateChildControls()方法
protected override void CreateChildControls()
{
this._innerControl = this.Page.LoadControl("/bin/History.ascx");
this.Controls.Add(this._innerControl);
}
再重载RenderWebPart()方法,输出载入的User Control:
protected override void RenderWebPart(HtmlTextWriter output)
{
this.EnsureChildControls();
this._innerControl.RenderControl(output);
}
5、最后编辑“WebPart1.dwp”,配置WebPart。编辑SPS虚拟站点上的“web.config”,添加“<SafeControl>”标签以信任我们的WebPart。在VS.NET中编译,生成最终的“LCS.dll”。将此(.dll)和History.ascx拷贝到SPS虚拟站点跟目录的“bin”目录下。在SPS站点页面中导入WebPart1.dwp。这样查询LCS聊天记录的WebPart就可以使用了。
本文只是大体讲解了一下整个过程,具体关于开发Webpart的教程可以下载Kaneboy写的PPT教程:
http://www.gotdotnet.com/workspaces/releases/releasedownloadhandler/download.aspx/7741ec2a-e7ab-41da-baef-a8efd2658895/85aefa87-fb76-4b32-ab12-31a4e647878a/download.zip
今天在digitalghost的博客上看到了他回忆大学生活的日记,也许是我们有些相似的地方,看了以后颇有感触。不禁又让我想起了一年前,想起了绝对与众不同的简历,想起了大学走过的日子。现在还不确定大学四年的经历对我今后会有怎样的影响,不知道我是否在正确的时间做了正确的事,留给时间去判断吧。
http://my.donews.com/digitalghost/2006/05/17/%e9%93%ad%e8%ae%b0%e8%bf%99%e4%ba%94%e5%b9%b4/
摘录其中两段
三、大四、大五在领悟中走过
平静的送走了我的同学们,在这个收获的季节。我没有像想象中那样惶恐不安,辗转反侧,相反,我和大家一起照了毕业照,吃了散伙饭。并非我好了伤疤忘了疼,而是我在这么长的时间里,渐渐领悟了这次降级赋予我人生的意义。人生的前十几年,我在父母的庇佑下长大,之后就狠狠摔了一跤,我想,这跤把我从迷茫中,天真中摔醒了,让我体会到人生的一些点点滴滴。这两年,我都在忙碌的工作中度过,同时兼顾着我学校的学业,很多时候想过要放弃,因为看到我眼前的工作不错,自己也有一些技能,觉得文凭无所谓了,可是我都打消了这个念头,因为我不想承认自己是懦夫,不想承认自己是轻言放弃的失败者,尽管我现在没有完全看清文凭对我人生的影响有多大,但是就冲着这次降级,我也要拿到文凭,结结实实的站起来,面对我自己。现在我在www.gbaopan.com工作,担任着web开发的主要任务,在不断的工作中,深知基础知识的重要性,体会到,现在个人技术层次无法提高的根本原因就在于内功不够过硬,数据结构,数据库等计算机系得看家本事没有修炼到位;说据很有感触的话:一个人的知识层次,直接决定了它思考和解决问题的方式,不要以为很多看似跟专业无关的知识就真的无关紧要,知识的根本作用在于启发我们思考,而不是他本身。
四、一切在收获的季节结束
收获的季节总是要收获,今秋这个收获的季节,我一路磕磕碰碰的走到了终点面前。今天的我,再也没有时间玩任何一个游戏,因为我知道我的人生不是游戏;也不敢再轻易的去和自己的时间开个玩笑,因为我知道我会付出生命的代价。
此刻,我很满足,因为写下这篇流水账,我知道我深深铭记住了我青春中珍贵的五年。
最近使用微软的Sharepoint Portal Server(SPS)为单位开发了新的门户网站,因为是微软自家的产品,因此与Active Directory、Exchange、LCS等都有很好的整合。在整个部署过程中发现有很多值得记录下来的经验,一方面用来备忘,一方面与朋友分享。
一、关于固定IP地址的问题
在安装完Sharepoint后,首先要对一个网站进行扩展,也就是新建一个门户网站。经过我的反复测试这里扩展的网站最好不要指定固定IP地址,否则在日后的使用中会出现很多问题,如Frontpage无法编辑页面,WEB内容编辑器webpart无法使用等。不知道这是SPS的bug还是我的bug…
二、关于匿名访问与用户登录
SPS更适用于一个公司或团队内部,并不对外开放。但是对外开放的需求也是很常见的,我们需要的就是对内部人员开放权限,对外部匿名用户只有阅读权限。SPS也有这样的匿名访问设置,但是设置以后,我们会发现内部用户也变成了匿名用户,连管理员都无法对网站进行管理。解决这个问题有两种方法,一是为网站设置两个入口,即一套数据承载两个入口,一个匿名一个需要身份验证。具体参见http://sps.forever.net.cn/oceanstudy/SharePoint/如何匿名访问SPS门户站点/anyosps.html 。另外也有一个更好的方法,就是在页面上放置一个“登录”按钮,这样不用设置两个入口,在匿名访问的页面上点击登录即可输入用户名和密码,更符合我们的习惯。设置方法如下:
step 1:将SPS开启匿名访问(IIS里开匿名,再在SPS的网站设置里开启匿名)
step 2:在c:\inetpub\wwwroot(这是对应SPS网站的虚拟目录)下的web.config里加入一个key:
<appSettings>
<add key=”SPS-EnforceIISAnonymousSetting” value=”false” />
</appSettings>
step 3:把WSS网站的登陆按钮用FrontPage2003直接拷贝到SPS网站上需要的位置上。这个按钮其实就是一个webcontrol:
<WebPartPages:AuthenticationButton runat=”server”/>
这样,登陆按钮就可以使用了。
三、浴火重生的Frontpage
曾几何时,Frontpage已经被我深深的遗忘和抛弃,Dreamweaver在很多方面都超越了他。但是微软就是微软,Frontpage因为SPS而重获新生。SPS的页面都是可以通过Frontpage来编辑的,比通过页面编辑功能更多,而且可以个性化定制。比如可以跨区域添加webpart、添加blog部件等。但是适用Frontpage编辑后页面的Ghosting Page特性会被破坏,对Ghosting Page的修改会记录在Docs表的Content字段中,默认时该字段为Null,但当我们修改后,该字段中就会用来存储我们的修改信息。要想还原其实就很简单了,只要把该字段置为空就行了。
四、如何去掉最上面的“帮助”链接
SPS页面最上方的“帮助”链接是写在webcontrol里的,我们无法通过常规方法修改掉。不过也有变通的方法,可以通过js脚本来完成。
基本操作过程如下:
1 定位OWSBROWS.JS文件,这个文件在%SystemRoot%\Program Files\Common Files\Microsoft Shared\Web Server Extensions\60\template\layouts\2052目录中
2 在该文件中加入一个Window Load事件响应函数,以删除帮助链接,源代码如下转载自MSD2D:
window.attachEvent(“onload”, new Function(“DelHelp_OnLoad();”));
function DelHelp_OnLoad()
{
try{
var aTags = document.getElementsByTagName(“A”);
for(var j=0;j<aTags.length;j++){
var aTag = aTags(j);
if(aTag.innerText==”帮助”)
{
aTag.innerText=”";
break;
}
}
}
catch(e)
}
}
3 保存后刷新网页即可看到效果
另:OWSBROWS.JS作用于所有网页,修改之后SPS所有网页都将没有帮助菜单。注意编辑OWSBROWS.JS文件时注意该文件是UTF-8格式,注意保持格式,特别是中文版SPS,我一开始没有注意,始终不能使aTag.innerText==”帮助”条件成立。 修改之后的效果你可以看到帮助链接一闪之后就消失了,这是因为实际上SPS是将该链接生成并送到浏览器了,而加入的代码在页面加载时在将该链接去掉所以看不到,实际上在页面的HTML源代码中还是看得到这个链接的。
五、如何为SPS的列表库设置权限
很多用户发现SPS权限设置的最小单位是区域,而不能想WSS一样为区域中的列表或文档库设置权限。其实是可以的,只是微软把这个功能给屏蔽了。我们分析数据库后就可以发现SPS的区域信息和WSS的网站存在一个表中,而他们的列表库也是存在另外一个表中。这样对比字段后就可以发现其中的奥秘。具体修改方法如下:
修改XXX_Site数据库中的Webs表的对应区域的记录的SecutiryPrivoder字段的值为NULL,在Portal站点中修改列表配置的页面中就会自动出现修改列表权限的链接。还应该注意webs表和webpart表中AnoymousPermMask字段的数值,该字段用来控制是否能够匿名访问,设置为0则无法匿名访问,196609则允许匿名访问。
六、关于公文流转
SPS 2003目前还没有自带公文流转的功能,kaneboy开发了一个webpart,不过使用效果也不是很好,还是让我们期待Office 12吧,新SPS将原生集成OA流程。