最近一个朋友问我一个问题:
如何可以将ASPdotNET Forum2.0放到他的一个项目中(好象网上也有人讨论过如何将dotText和ASPdotNET Forum等开源项目集成起来的),他原来的项目已经有一套用户登录机制了,而且用户数据库也是现成的,如何使得在他原来系统上登录后就可以直接转到Forum上,而又不需要再次输入用户信息呢?刚开始感觉a piece of cake...象这种一次登录,然后可以访问多个应用其实在很久就已经提出来了,在几年前还帮公司做过一个类似的产品原型,但那个是针对异构网站的,说白了就是做一个代理,只是内部有套机制将后面的几个异构网站的用户数据库映射起来而已。这种方式看起来似乎可以解决问题,但数据库之间的映射关系处理起来很麻烦,如果下面应用多了的话,工作量是很大的。
对于这种技术,似乎有个名词叫Single Sign On,有点象网易的通行证了。如果内部网站是同一批人做的倒问题不大,只要协调好了这个通行证的格式和一些相关的问题就可以了。而朋友的情况似乎也没有那么复杂,他原来的项目也是用.NET平台技术的。.NET平台下是否有比较好的整合解决方案呢?
这自然涉及到了.NET平台下验证的相关问题了。ASP.NET自身已经支持三种验证方式(不包括None):
1. Windows身份验证,新建立一个Web应用,似乎缺省就是用这样的方式的。显然这个不是需要的。
2. Passprot身份验证,需要Microsoft支持,它其实提供了一个WebServices来帮助你统一完成验证工作,使 用这个在内部 网项目中似乎没有太大必要。
3. Forms身份验证,通过Cookie来传递身份验证信息,看起来类似通行证之类的,应该是要找的东西了。
图是Forms身份验证的数据流程图(MSDN中的)
上图十分清晰的描述了Forms身份验证的基本原理,但是对于多个应用呢?仔细查MSDN(MSDN真的好多资料啊,经常看过了再想翻回去已经忘记在那里找出来的了 BTW:有没有MSDN书签功能的?),发现相关的描述很多,但只有一个“跨应用程序进行Forms 身份验证”比较具体,而内容就简单些了。
看来还是需要自己先动手做个简单的测试来边试边查资料了...
先建立一个testLogon的Web应用
主要文件包括:
default.aspx (通过验证跳入的页面)
test1.apsx (登录的页面)
Global.asax
Web.config (配置文件)
再建立另外一个testLogon2的Web应用
主要文件:
default.aspx (通过验证跳入的页面)
Global.asax
Web.config (配置文件)
测试最终达到的效果:
两个Web应用的default都是受保护的,没有通过验证是不可以进入的,即使在输入访问地址URL,会自动跳转到testLogon\test1.aspx要求登录,当登录通过后,则可以任意在两个应用的default.aspx跳转。
testLogon\default.aspx中有Logout的功能,Logout后则需要重新登录了。
要达到这个效果,基本设置需要:
1.将IIS配置为允许匿名访问,保证可以通过IIS来控制传递请求给ASP.NET;
2.如果必要传输过程配置为SSL,这里没有这个必要了;
3.对应的两个应用的配置文件必须设成一致;
以上这些基本设置在MSDN中都可以找到相关的描述,但是实验这个效果到成功却花费了比预计长的时间,因此觉得十分有必要将其记录下来,对自己对他人都有好处。
得到的经验教训如下:
1.配置文件Web.config中,将验证模式设为Forms,而且在下面的参数中,要保证两边一致
testLogon的Web.config对应部分
<forms name=".AspNetForums" protection="Encryption" timeout="60" loginUrl="test1.aspx" />
</authentication>
testLogon2的Web.config对应部分
<forms name=".AspNetForums" protection="Encryption" timeout="60" loginUrl="\testLogon\test1.aspx" />
</authentication>
2.<machineKey>的增加是必须的
为保证两边两边应用对cookie的处理和读取一致,这个属性是必须的,且要相同
validationKey= "C50B3C89CB21F4F1422FF158A5B42D0E8DB8CB5CDA1742572A487D9401E3400267682B202B746511891C1BAF47F8D25C07F6C39A104696DB51F17C529AD3CABE"
decryptionKey= "8A9BE8FD67AF6979E7D20198CFEA50DD3D3799C77AF2B72F"
validation="SHA1">
</machineKey>
3.MSDN虽然要查,但不可以完全依靠,特别是代码
在MSDN中,关于machineKey的代码如下:
<system.web>
<authentication>
<forms name=".ASPXAUTH"
loginUrl="logon.aspx"
protection="all" <!-- Protection must be identical.-->
timeout="30"
path="/" > <!-- Path must have a compatible scope.-->
</authentication>
<!-- Validation and decryption keys must exactly match and cannot
be set to "AutoGenerate". The validation algorithm must also
be the same. -->
<machineKey>
validationKey= "C50B3C89CB21F4F1422FF158A5B42D0E8DB8CB5CDA1742572A487D9401E3400267682B202B746511891C1BAF47F8D25C07F6C39A104696DB51F17C529AD3CABE"
decryptionKey= "8A9BE8FD67AF6979E7D20198CFEA50DD3D3799C77AF2B72F"
validation="SHA1"
isolateApplications="false"
</machineKey>
</system.web>
</configuration>
但显然有着错误的,大家编译一下就知道了,格式错了,而且isolateApplication也不是这样用的
4.为保证两边读到的cookie一致,不要用isolateApplication,它使得各自用自己的cookie了。
5.关于Global.asax的注意,对于Web.config中authentication的节点会触发Global.asax中的事件的,对应
函数是
6.研究一下ASPdotNetForum2.0代码发现,Global.asax不见了,而在它的配置文件中多了一项
<add name="AspNetForums" type="AspNetForums.ForumsHttpModule, AspNetForums.Components" />
</httpModules>
是的,看一下ForumsHttpModule的源码,结构和Global.asax基本一样,一样有个事件触发函数
下面不用我多说了吧?具体该如何做到和dotNetForum一起达到SSO的目标的答案已经出来了