所谓的单一登录是指用户在一个站点如www.studyez.com登录后切换到另一个站点communty.studyez.com时也自动 被community的Server判断为已经登录,反过来,只要用户在community.studyez.com登出后,切换到 www.studyez.com时后www的Server也会判断到这一用户已经登出。
限制条件:
1.所有要求单点登录的站点间共享同一用户数据库,这点应该不需要任何解释的吧。
2. 要求所有站点在同一父域名之下。这里所说的单点登录是指在同一个域名下不同子域名之间的单点登录,直接的例子就是像这样的站点之间的跨站单点登 录: www.studyez.com, community.studyez.com, serach.studyez.com, mail.studyez.com, mms.studyez.com 等, 他们属于一个共同的父域名studyez.com, 之所以有这么多子域名,是因为有很多子系统的时候用不同的子域名对于开发、部署和管理都能方便很多, 而且对于用户访问量很大的站点,可能每个子域名都会有很多的服务器来伺服。这是比较符合目前很多站点的模式和需求的。
对于非同一父域名下的域名间跨站登录,最好的方式是采用Passport的原理来实现,具体实现可以参考Passport文档,因此不在本文讨论范围之内。
原理:
在不同的子域名之间实现单点登录的最佳途径是采用Cookie的Forms认证。他的原理简单的来说,就是让Forms Authentication生成的Cookie能够跨域名访问。
先谈一下Cookie的限制,对于一个任何Http Request来说,提交给Server端的时候,它能够安全访问的Cookie的域名必须在这个HTTP Reuqest的域名路径中。举例来说,发出一个http://communiy.corp.studyez.com/的 请求时,随着这个http request一块发送到server端的cookies会自动包括所有 以 community.corp.studyez.com, .corp.studyez.com, corp.studyez.com, .studyez.com, studyez.com 为域名的Cookies,这是由Cookie本身的规范所限制的,浏览器如果不是按照这个规范实现,那么就会存在严重安全漏洞,因为那样的话意味着任何一 个服务器都可以读到同一个用户访问别的网站时留下的Cookie。
根据上面所述Cookie的限制性,可以得出,对于前面 www.studyez.com, community.studyez.com等站点的例子来说,就是想办法如何让 Forms Authentication生成的Cookie的域名限定为.studyez.com或者studyez.com,而不是默认的 www.studyez.com 和 communty.studyez.com,这样就使得单一登录需求的实现成为可能。
今天先写这么多,接下来几天会继续写实现和局限性。
程序代码// 用户 Cookie 存储键
public const string CookieUser = "devin_cn_user";
// 用户Cookie名称键
public const string CookieUserName= "UserName";
///
/// 设置用户 Cookie 信息
///
/// 用户名称
/// Cookie有效时间选择值
private void SetCookie(string UserName,int CookieSave)
{
//设置Cookie值
HttpCookie cookie = new HttpCookie(CookieUser);
//设置域Cookie
cookie.Domain = ".devin.cn";
//设置用户名称
cookie.Values.Add(CookieUserName, UserName);
//设置Cookie身份验证码
cookie.Values.Add(CookieUserCode, this.CookieCode().ToString());
//根据选择,设置Cookie有效时间
switch (CookieSave)
{
case 0:
cookie.Expires = DateTime.Now; //即时
break;
case 1:
cookie.Expires = DateTime.Now.AddDays(1); //一天
break;
case 2:
cookie.Expires = DateTime.Now.AddDays(7); //七天,一周
break;
case 3:
cookie.Expires = DateTime.Now.AddMonths(1); //一月
break;
case 4:
cookie.Expires = DateTime.Now.AddYears(1); //一年
break;
}
//在保存 Cookie 信息之前,删除原有Cookie信息以避免重复
HttpContext.Current.Response.Cookies.Remove(CookieUser);
//保存Cookie信息
HttpContext.Current.Response.SetCookie(cookie);
//登陆认证
FormsAuthentication.RedirectFromLoginPage(UserName,false);
}
就是这一句吧
//设置域Cookie
cookie.Domain = ".devin.cn";