再转载点内容:
昨天和几位朋友探讨到了这个话题,发现虽然单点登陆,或者叫作独立的passport登陆虽然已经有了不少实现方法,可是能真正了解并实现的人却并不太多,因此些下此文,但愿从原理到实现,能让你们了解的多一些cookie
至于什么是单点登陆,举个例子,若是你登陆了msn messenger,访问hotmail邮件就不用在此登陆。
通常单点登陆都须要有一个独立的登陆站点,通常具备独立的域名,专门的进行注册,登陆,注销等操做
咱们为了讨论方便,把这个登陆站点叫作站点P,设其Url为http://passport.yizhu2000.com,须要提供服务的站点设为A和B,跨站点单点登陆是指你在A网站进行登陆后,使用B网站的服务就不须要再登陆
从技术角度讲单点登陆分为:
- 跨子域单点登陆
- 彻底跨单点域登陆
跨子域单点登陆
所谓跨子域登陆,A,B站点和P站点位于同一个域下面,好比A站点为http://blog.yizhu2000.com B站点为 http://forum.yizhu2000.com,他们和登陆站点P的关系能够看到,都是属于同一个父域,yizhu2000.com,不一样的是子域不一样,一个为blog,一个为forum,一个是passport
咱们先看看最经常使用的非跨站点普通登陆的状况,通常登陆验证经过后,通常会将你的用户名和一些用户信息,经过某一密钥进行加密,写在本地,也就是一个加密的cookie,咱们把这个cookie叫作--票(ticket)。
须要判断用户是否登陆的页面,须要读取这个ticket,并从其中解密出用户信息,若是ticket不存在,或者没法解密,意味着用户没有登陆,或者登陆信息不正确,这时就要跳转到登陆页面进行登陆,在这里加密的做用有两个,一是防止用户信息被不怀好意者看到,二是保证ticket不会被伪造,后者其实更为重要,加密后,各个应用须要采用与加密一样的密钥进行解密,若是不知道密钥,就不能伪造出ticket,
(注:加密和解密的密钥有可能不一样,取决于采用什么加密算法,若是是对称加密,则为同一密钥,若是是非对称,就不一样了,通常用私钥加密,公钥解密,可是不管怎样,密钥都只有内部知道,这样伪造者既没法伪造也没法解密ticket)
跨子域的单点登陆,和上述普通登陆的过程没有什么不一样,惟一不一样的是写cookie时,因为登陆站点P和应用A处于不一样的子域,P站写入的cookie的域为passport.yizhu2000.net,而A站点为forum.yizhu2000.net,A在判断用户登陆时没法读到P站点的ticket
解决方法很是简单,当Login完成后P站点写ticket的时候,只需把cookie的域设为他们共同的父域,yizhu2000.net就能够了:cookie.domain="yizhu2000.net",A站点天然就能够读到这个ticket了
ASP。Net的form验证自己实现了这个机制,你们能够参考http://blog.csdn.net/octverve/archive/2007/09/22/1796338.aspx
ASP.NET身份验证信息跨域共享状态
在ASP.NET 2.0 中只需修改web.config文件便可,修改方法以下:
<authentication mode="Forms">
<forms name=".ASPNETFORM" domain="imneio.com" loginUrl="/login.aspx" defaultUrl="/default.aspx" protection="All" timeout="30" path="/" requireSSL="false" slidingExpiration="true" enableCrossAppRedirects="false" cookieless="UseDeviceProfile" />
</authentication>
domain指定了cookie保存的域,只要保存的是 abc.com形式或者.abc.com的形式,那么其二级域名均可以共享此cookie。
此外,web.config标签中的<sessionState >也作相应修改,mode改成StateServer或者SqlServer,那么里面的session信息也就所有能够共享了。
StateServer须要在服务中开启“asp.net状态服务”的服务。
http://www.imneio.com/2007/11/17/aspnetnote1/,以上斜体内容摘自此连接
彻底跨单点域登陆
彻底跨域登陆,是指A,B站点和P站点没有共同的父域,好比A站点为forum.yizhu1999.net,B站点为blog.yizhu1998.net,你们能够参考微软旗下的几个站点http://www.live.com,www.hotmail.com,这两个站点就没有共同的父域,而仍然能够共用登陆,怎样才能实现呢?请参考下图,因为这种状况ticket比较复杂,咱们暂时把P站点建立的的ticket叫作P-ticket,而A站点建立的ticket叫A-ticket,B的为B-ticket
因为站点A(forum.yizhu1999.com)不能读取到由站点P(passport.yizhu2000.com)建立的加密ticket,因此当用户访问A站点上须要登陆才能访问的资源时,A站点会首先查看是否有A-ticket,若是没有,证实用户没有在A站点登陆过,不过并不保证用户没有在B站点登陆,(重复一下,既然是单点登陆,固然不管你在A,B任意一个站点登陆过,另一个站点都要能够访问),请求会被重定向到p站点的验证页面,验证页面读取P-ticket,若是没有,或者解密不成功,就须要重定向登陆页面,登陆页面完成登陆后,写一个加密cookie,也就是P-ticket,而且重定向到A站点的登陆处理页,并把加密的用户信息做为参数传递给这个页面,这个页面接收登陆页的用户信息,解密后也要写一个cookie,也就是A-ticket,从此用户再次访问A站点上须要登陆权限才能访问的资源时,只须要检查这个A-cookie是否存在就能够了
当用户访问B站点时,会重复上面的过程,监测到没有B-ticket,就会重定向到P站点的验证页面,去检查P-ticket,若是没有,就登陆,有则返回B的登陆处理页面写B-ticket
注销的时候须要删除P-ticket和A-ticket
怎么删除cookie:原本觉得这个不是问题,不过仍是有朋友问道,简单的说实际上是建立一个和你要删除的cookie同名的cookie,并把cookie的expire设为当前时间以前的某个时间,不过在跨子域的删除cookie时有一点要注意:必需要把cookie的域设置为父域,在本文中为yizhu2000.com
为了保证各个环节的传输的安全性,最好使用https链接