** Hi, 现在我们暂时不谈 Passport **
小气的神
2002 . 02 . 16
Article Type: In-Depth
难度等级: 6/9
版本: 1.27
在我写了那篇 Passport 你的网站之后,我发现自己犯了一个错误,从一开始。也许当时只是想表达自己对 Passport 的喜爱和接触之后还算美好的虚荣感受。我想在当时陶醉时,肯定刻意忽略了其它的某种因素。不然当计划正式开始使用它时,不会发现它突然带有了某种不确定性,甚至退后到测试的机器上也不能工作了;多次再去做和对着文档去想了又想,开始有些惭愧,因为我发现那篇文档几乎毫无用处,这将是一次名不其实表述,那么对于一个技术人员来说,这种感受是痛伤的,同时对他来说也将是个教训。
不过 Passport 的重要性丝毫不亚于它的复杂和繁琐,无法预知 Microsoft 将如何改善这种长距离的集中验证所带来的不确定“刺耳音符”,但在未来可以看到的体系和应用中,避而不见 Passport ,也意味着今后你在 MS 平台上要冒更多的风险。那么对于“是否需要接触 Passport ?”、“现在是否需要学习了解 Passport ?”这样问题的答案都应该是慎重的“应该”,放弃观望的态度将是一个好的开始。我们可以在接触学习中等待 3.0 版本的 Passport ,不过在没有更好的 Demo ,没有我们需要的 Help 文档的一段时间里,现在我们暂时不谈 MS 的 Passport 。它依然复杂得超出我们的理解,我们只能一点点去尝试和了解,做那些我们力所能及的事。最后欢迎回到这个脆弱而迷幻的世界,它依然充满失落和期待。
下面将是一个 Passport 的实现 ( 我猜是最小的一个框架 ) ,它的最初是 Nathan Smith ([email protected] ) 示范性的一个 dotNET β 2 的版本,调试时我进行了一些小的改动(不少改进吧,但主框架没动),并且添加了一个简单的测试前端。在我升级到 dotNET 1.0 后,重新测试了它,所以它需要的环境可能是:
Windows 2000 Server , MS SQL 2000 SP2 (中文或英文), dotNET SDK 1.0 , VS.NET RTM,IIS 5.0 SP, IE6 2813
数据结构:
设计两个数据库 :PassportSvr , PassportClient
PassportSvr:
PassportClient:
另外还有下面这些实现核心功能的存储过程:
** sp_registerUser **
** sp_setUserInfo **
** sp_setUserPassword **
** sp_setUserStatus **
** sp_purgeUser **
** sp_setUserHomeService **
** sp_validateUser **
** sp_registerService **
** sp_setServiceInfo **
** sp_setServicePassword **
** sp_setServiceStatus **
** sp_purgeService **
** sp_validateService **
应用实现:
根据上面的数据结构实现了两个 Web Services ,一个作为整体的 Services 的管理接口,一个是提供给最终用户使用的 Client Services 接口。
看得出来最终提供给用户使用的只有 7 个函数,当然开始时你可以在调试 Services WebServices 时测试一下 RegisterService 函数,它将建立一个 Services ,记下 services_name 和 services_password , 在实现 Client 的 WebService 的 Global.cs 中有这样应用:
protected void Application_Start(Object sender, EventArgs e)
{
DataManager.InitManager();
Passport ppSvc = new Passport();
AppTicket = ppSvc.AuthenticateService( ** "Passport","passport" ** );
ppSvc=null;
}
整个实现中有个与 Passport 相似的安全机制- Ticket ,当用户通过验证之后获得一个 AuthenticationTicket 并产生一个 Token ,我认为这里是最有趣和最棒的部分,简单有效。
** Ticket Structure **
public class AuthenticationTicket
{
public AuthenticationTicket()
{
}
** public int Token; **
public int OwnerID;
public double ExpirationDate;
public double IssueDate;
public string NickName;
public string FirstName;
public string LastName;
}
** Token Generation Routine **
static private int GenerateToken(int systemID, string nickName,
int passwordHash, double issueDate, double expirationDate)
{
int rtn; // our return value
string s_token; // string concatenation of the objects
// concatenate all of our values together.
// note the use of hashing the password and the id, this
// should help reduce the probability of attack
s_token=systemID.GetHashCode().ToString() +
nickName + passwordHash.GetHashCode().ToString() +
issueDate.ToString() + expirationDate.ToString();
// get the hash of the concatenation and return it
rtn=s_token.GetHashCode();
return rtn;
}
好了解决了主要问题,后面的实现的就迎刃而解了,下面分别是两个 Web Services 暴露的功能函数。
** public AuthenticationTicket AuthenticateService **
** public AuthenticationTicket AuthenticateUser **
** public AuthenticationTicket CreateAccount **
** public int DisableAccount **
** public int EnableAccount **
** public int PurgeAccount **
** public int SetAccountHome **
** public int SetAccountInfo **
** public int SetAccountPassword **
** public int SetServiceInfo **
** public int SetServicePassword **
** public int RegisterService **
** public bool ValidateServiceTicket **
** public bool ValidateUserTicket ** ** **
看得出真正 Client端用的接口很简单和明了,(这是又一个不错的亮点) 如果一切 OK ,那么你点击 RegisterAccount ,输入需要的数据,如果正确那么返回下面的结果:
剩下的工作我想就是包装一下,用一个 ASP.NET 的 Web Form 再测试和使用了。
结论:
这将是一个可能的 Passport 的实现,当然不是全部,但如果不是必须并不建议将其使用在正式的应用中,但你可以从下面的建议中去加强和衍生扩展它:
1. 体系结构上用了最新的 Web Services ,或许原来的作者太喜欢 Web Services 了,所以用得可能太多了,那么最可能是在这个例子中你可以看到 Web Services 事务不完整的现象,当一个 We 调用时,有时我们会发现只有一个数据库中有数据。
2. 构造实现时使用了 SQL 2000 的 XML 特性,尽管向大家展示了 SQL 2000 的方便特性( Nathan Smith 是个 MCSD haha ),对于要使用 Oracle , IBM 数据库的需求,也就意味着某种不可移植性,这部分代码必须重新考虑和写过。
3. 作为一个应用的核心功能部分,目前完全的 Web Services 构架是过于单薄和松散,必须考虑 Window Services 和线程池的实现来提升性能,同时对程序的构架做一个调整。
4. 数据库设计不完全,需要再细化和重新根据需求进行设计,添加表。记住目前它仅是一个 Demo
5. Nathan Smith 把数据库的连接放在 Goalx 的文件中,似乎想节省建立 Connection (当然这是一种有些糟糕但是省力的作法),在我测试中发现负责指向第二个数据库连接经常并没有建立,在没有自己实现事务保证的情况下,它往往是数据不完整的主要原因(我已将所有的数据库连接移到了函数内部),所以根据可能需要加入可靠的 DAL 层。
自从 1989 年 Microsoft 从 Firefly Network 购买 Passport 之后, Passport 在用户数和功能上不断的在发展, 1.4 版本展示了两个大的功能 : Single Sign In (SSI) 和 Express Purchase(EP).2.0 版本主要是提供一个完整的 COM 接口(很类似 WinInet API ),内嵌的界面( embedded Passport UI ),更重要的是向基于 Kerberos 的 Authentication 迈进。可以预见到未来的 2.1 或 3.0 版本,它会增强对 IE6 、 P3P 以及 WAP 、 HDML 、 Microsoft Mobile Explorer 、 PocketPC 等移动设备的支持,更重要的是对基于 XML 信息处理的支持(目前的 Passport 的体系结构中 Client 、 Participating website 和 Microsoft Passport server 像一个三角形,在 SSI 或 EP 时 websit 和 Passport Server 之间并不直接通讯,而是借助 Client 使用 HTTP 查询字符串和 HTTP Redirect 来传递信息,所有需要存储的数据比如登录状态、用户 Profile 是依赖于用户端的 cookie ), Passport 将成为 Hailstorm 的关键服务,那么对 XML 的支持是必须的,另外和目前已有的 Hailstorm 服务之间功能的整合也将是大的挑战, Passport 最大的机遇不是推出它的 dotNET 版本,而且它如何成为一个又是中心化验证,又提供个性化服务的框架,它正式的推出也将是整个 Hailstorm ( .Net My Services )服务吹响冲锋号角的一个前兆。
无论外界如何评论或是如何和自由联盟争斗,“今天的 Passport 不等于明天的 Passport ”(李开复语),未来并不总是一片光明甚至不会一帆风顺。“当我们的路通向一个黑暗的森林,追寻来时的脚步是多么困难。当路被设定好,回归似乎不可能。生命就是我们的契约,除了最高法庭之外,无人能撤销它。”, Passport 也是一样:战斗需要更多的炮火,时代早已充满革命,更好的活着是它最超越的荣耀。
相关的文件下载: ** [Project for RTM] ** ** [PassportOld] **
<FONT face="Lu