欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP.NET中在不同的子域*享Session的具体方法

程序员文章站 2024-02-29 17:05:46
今天遇到了这个问题,于是研究了一下。要解决这个问题,首先就要明白一些session的机理。session在服务器是以散列表形式存在的,我们都知道session是会话级的,每...

今天遇到了这个问题,于是研究了一下。要解决这个问题,首先就要明白一些session的机理。session在服务器是以散列表形式存在的,我们都知道session是会话级的,每个用户访问都会生成一个session。那么服务器是怎么区分不同用户的session?又是怎么将不同用户的session与不同的用户绑定的呢?下面我们来研究一下,以下纯属我个人的理解,如有错误请指证。

session在服务器端是以散列表的形式存在的,区分每一个session是通过sessionid来实现的,所以可以说这个sessionid是一个key是一个全局唯一的值。我们可以通过asp.net来打印出sessionid,如下代码:

复制代码 代码如下:

protected void page_load(object sender, eventargs e)      
{            
response.write(session.sessionid.tostring());     
}

这样我们就得到了这样的值:0julmoedn0kz3gyfnr1vksv0,有点像是guid,就算不是算法也都是类似的,主要就是为了保证全局唯一性。这样就达到了区分不同用户的session的目的。接下来还有第二个问题,那就是sessionid有了,但是它又是怎么和相应的访问者(用户)绑定的呢?比如说用户a访问维护了自己的sessionid,用户b访问也维护了自己的sessionid。我们都知道web是基于http无链接的,他们又是怎么做到的呢?没错,答案就是在客户端存储了自己的sessionid。浏览器存储sessionid有两种方式,一种就是利用cookies;还有一种就是利用url参数(这种我们不常用,很不友好)。

话题说到cookies上来了,怎么的?没想到session和cookies还有这样的关系吧?(很多人知道,别bs我)没错,当我们请求一个url时候,服务器会生成一个全局的sessionid,并且把这个值以cookies的形式保存在客户端也就是浏览器(这里暂不讨论url方式)。这样当用户再去请求的时候,在http头把这个sessionid的cookie发到服务器端,服务器就去找这个sessionid,如果找到了。就证明这个用户的状态是存在的。

知道了这个原理,我们的问题也就有眉头了,即然是用cookies来保存sessionid,那么我们就可以在cooikes上做手脚了。我们都知道cooikes记录方式是以域(例如://www.jb51.net/)为区分的,这也是各种浏览器规定的。如果不这么做,安全性就会有问题。我们要做的就是让指定cookies的父域方式,不指定具体指域,这样cookies就可以跨子域了。cookies可以像这样指定域:

复制代码 代码如下:

protected void page_load(object sender, eventargs e)       
{            
response.cookies["mycook"].domain = ".jb51.net";   
}

  这样,我们所有的二级域全部是认这一个主域的,比如a.jb51.net;b.jb51.net;user.jb51.net等等。有了这个认识,我想大家心里也有数了,该怎么怎么做,但是现在问题是用来生成sessionid的方法是asp.net自动实现的,我们又怎么去干涉它呢?这是这样做的,不主动干涉它,但是我可以操作它的cookies啊。接下来我们就研究asp.net存sessionid的cooike的名字是什么。经过网上很容易就查找到了,名字是:asp.net_sessionid,这个就是sessionid的cookies名字。我们可以在session_start中这样写:

复制代码 代码如下:

protected void session_start(object sender, eventargs e)      
{           

response.cookies["asp.net_sessionid"].value = session.sessionid.tostring();  

response.cookies["asp.net_sessionid"].domain = ".jb51.net";     

}

代码的意思是每次会话开始的时候,我都把asp.net_sessionid这个cookie重写成我们已有的sessionid,并且把这个cookie的domain指定为父域,比如:.jb51.net,这样就可以实现跨子域的session共享了。怎么样很简单吧?

我们还有一个外题问题,就是客户端保存的问题解决了,但是服务器端的session怎么办?一般情况下我们不同的子域做的是指向不同的服务器的,比如user.jb51.net 专门一台服务器,yellow.jb51.net专门一台服务器。这时它们别说是进程了,连物理上都不是一个了。session怎么共享?这时就用到另一个方法了,我们默认的session是存储在asp.net进程中的,这样没法互相访问,如下面所示:

复制代码 代码如下:

<sessionstate mode="inproc" />

我们可以修改为state server方式,这是一个单独的服务可以用来存储asp.net session的,它支持分布式远程主机的,这样我们可以用一台服务器来提供session服务,如下所示:

复制代码 代码如下:

<sessionstate mode="stateserver" stateconnectionstring="tcpip=127.0.0.1:42424" timeout="30" />

这样,就完全实现了不同子域的session共享了。

前面说到url保存sessionid的方式,由于不常用,给大家演示一下,如下配置就可以了:

复制代码 代码如下:

<sessionstate mode="stateserver" stateconnectionstring="tcpip=127.0.0.1:42424" timeout="30" cookieless="true" />

cookieless属性指定是否用cookie来保存sessionid,我们运行一下得到下面的样子:

http://localhost:3380/(s(dqxcs455n4u2vg55ia51fvqg))/default.aspx