Robin's Blog

记录 积累 学习 成长

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
我的前面一篇文章提到了如何在使用了ASP.NET form authentication的二级站点之间共享登陆状态,

http://www.cnblogs.com/jzywh/archive/2007/09/23/902905.html

今天, 我要写的是如何在二级域名站点之间,主站点和二级域名站点之间共享Session。

 

首先, Session要共享,站点之间SessionID必须要一致,那怎么保证SessionID一致呢?

ASP.NET中的SessionID是存储在客户端的cookie之中键值为ASP.NET_SessionId用来维护浏览者Session对应关系的一个字符串,要想在二级域名站点之间,主站点和二级域名站点共享SessionID就必须先共享,那么我们就必须先实现ASP.NET_SessionId这一cookie的共享。

CrossDomainCookieModule

------------------------------------------------------------------------------------------------

public class CrossDomainCookie : IHttpModule
{
private string m_RootDomain = string.Empty;
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
m_RootDomain = ConfigurationManager.AppSettings["RootDomain"];
context.EndRequest += new System.EventHandler(context_EndRequest);
}
void context_EndRequest(object sender, System.EventArgs e)
{
HttpApplication app = sender as HttpApplication;
for (int i = 0; i < app.Context.Response.Cookies.Count; i++)
{
app.Context.Response.Cookies[i].Domain = m_RootDomain;
}
}
#endregion
}

 

上面的Module重设了所有cookie的domain到root domain, root domain在web.config中设置。也许有人会说这是眉毛胡子一把抓重写了所有cookie的domain, 那他也可以判断一下cookie的name, 如果为ASP.NET_SessionId的话才重写。

 

如果主站点和二级域名站点是同一站点,那么做到这一步,你的session就已经共享了,因为Session的ID是相同的,而且Session容器也是同一个。

 

如果主站点和二级域名站点是两个不同站点,则需要进行更多的操作了。

 

如果两个站点是不同的服务器的话,解决方法要简单点:

1) 使用相同的state server来存储Session.

2) 在两个站点的web.config设置相同的machineKey.

MachineKey的设置请参考http://msdn.microsoft.com/zh-cn/asp.net/w8h3skw9.aspx

3) 给两个站点设置相同name

这样做是为了确保两个站点的siteID相同,siteID是site name的hash值,注意请不要使用默认站点,因为默认站点的siteID并非site name的hash.

 

如果两个站点是在同一的服务器的话,需要对CrossDomainCookie再作一下修改,此方法也可应用于两个站点在不同服务器的情况:

1) 使用相同的state server来存储Session.

2) 用反射来设置System.Web.SessionState.OutOfProcSessionStateStore的静态字段s_uribase的值

 public class CrossDomainCookie : IHttpModule
{
private string m_RootDomain = string.Empty;
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
m_RootDomain = ConfigurationManager.AppSettings["RootDomain"];
Type stateServerSessionProvider = typeof(HttpSessionState).Assembly.GetType("System.Web.SessionState.OutOfProcSessionStateStore");
FieldInfo uriField = stateServerSessionProvider.GetField("s_uribase", BindingFlags.Static | BindingFlags.NonPublic);
if (uriField == null)
throw new ArgumentException("UriField was not found");
uriField.SetValue(null, m_RootDomain);
context.EndRequest += new System.EventHandler(context_EndRequest);
}
void context_EndRequest(object sender, System.EventArgs e)
{
HttpApplication app = sender as HttpApplication;
for (int i = 0; i < app.Context.Response.Cookies.Count; i++)
{
app.Context.Response.Cookies[i].Domain = m_RootDomain;
}
}
#endregion
}

 

完成这样的修改之后就可以实现Session的共享了。

 

同样如果你是使用SQL server来存储Session, 也可以使用类似的方法来解决Session共享问题。

--------

Masoud的《Understanding Single Sign-On in ASP.NET 2.0http://aspalliance.com/1545_Understanding_Single_SignOn_in_ASPNET_20.all
讨论了在Asp.net 2.0的程序场中,实现SSO的一种简便方式,如果你的企业的所有需要实现SSO的系统都是基于asp.net2.0实现的,那么你可以用这种方式,文中还有Demo下载[Download Sample]
在Asp.net 2.0的Web.config文件中的<system.web>节中有一个<machineKey>节点,需要实现SSO的程序保持<machineKey>的同容相同即可
<machineKey       
validationKey="282487E295028E59B8F411ACB689CCD6F39DDD21E6055A3EE480424315994760ADF
21B580D8587DB675FA02F79167413044E25309CCCDB647174D5B3D0DD9141"

decryptionKey="8B6697227CBCA902B1A0925D40FAA00B353F2DF4359D2099"      
validation="SHA1"/>

同时设置成为form认证,把登录指向同个页面
<authentication mode="Forms">
<forms loginUrl="http://localhost/Aspalliance1/login.aspx" name=".ASPXAUTH"/>
</authentication>

。由于<machineKey>中包含了敏感信息,所以作者建议实际应用当中应该把<machineKey>进行加密存储,用的时候再解密,作者在演示程序中还提供了加密解决的函数。

刚看到宝玉的对《Understanding Single Sign-On in ASP.NET 2.0》一文的补充 文中谈到了保持<machineKey>相同实现SSO的原理是基于同一域下的虚拟目录的cookie是可以共享的,然后 MachineKey的一致,确保了cookie的解密和解密的结果是一致的。这仅是解决了同一域下的虚拟目录不同的SSO的问题,如果对于同一主域不同 子域之间的cookie共享,需要设置如下
<authentication mode="Forms"> <forms loginUrl="login.aspx" name=".ASPXAUTH" domain="joycode.com"/> </authentication>
posted on 2009-03-10 11:42  Robin99  阅读(1332)  评论(0编辑  收藏  举报