惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Project Zero
Project Zero
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Scott Helme
Scott Helme
Know Your Adversary
Know Your Adversary
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
WordPress大学
WordPress大学
AWS News Blog
AWS News Blog
小众软件
小众软件
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Jina AI
Jina AI
AI
AI
美团技术团队
人人都是产品经理
人人都是产品经理
S
Secure Thoughts
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
宝玉的分享
宝玉的分享
Security Latest
Security Latest
P
Privacy & Cybersecurity Law Blog
C
Cisco Blogs
大猫的无限游戏
大猫的无限游戏
Google Online Security Blog
Google Online Security Blog
L
LINUX DO - 最新话题
罗磊的独立博客
Recent Announcements
Recent Announcements
H
Hacker News: Front Page
博客园 - 【当耐特】
K
Kaspersky official blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
SecWiki News
SecWiki News
Schneier on Security
Schneier on Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Apple Machine Learning Research
Apple Machine Learning Research
F
Full Disclosure
Google DeepMind News
Google DeepMind News
V
V2EX
博客园 - 聂微东
量子位
云风的 BLOG
云风的 BLOG
C
Check Point Blog
J
Java Code Geeks
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
W
WeLiveSecurity
Engineering at Meta
Engineering at Meta
V2EX - 技术
V2EX - 技术
Vercel News
Vercel News
L
LINUX DO - 热门话题
T
The Exploit Database - CXSecurity.com
L
Lohrmann on Cybersecurity
The GitHub Blog
The GitHub Blog

博客园 - leonardleonard

sql去重 分布式云存储系统 Riak CS 开源 转-WCF详解文档最新 .net 基础 HTTP 状态代码 大型网站架构不得不考虑的10个问题 怎么让蜘蛛喜欢你的网站 【Helper】泛型类和集合类的方法 靠垃圾站已经不能继续混下去了 初学做网站的草根站长必读 怎么样让网站有一个好听的中文名称 网站迅速产生外链的方法秘笈 想做成功网站需要注意的几个问题 一些JSON相关的函数 - leonardleonard - 博客园 21世纪开运网www.21kaiyun.com用javascript替换URL中的参数值的技巧 jquery技巧总结 JavaScript函数 this调用规则 只需九步让你新站成为高权重网站 影响Lucene索引速度原因以及提高索引速度技巧
Asp.NET 的Session实现原理 转自21kaiyun.com
leonardleonard · 2010-07-29 · via 博客园 - leonardleonard

 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记录方式是以域(例如21世纪开运网:http://www.21kaiyun.com/)为区分的,这也是各种浏览器规定的。如果不这么做,安全性就会有问题。我们要做的就是让指定Cookies的父域方式,不指定具体指域,这样Cookies就可以跨子域了。Cookies可以像这样指定域:

 protected void Page_Load(object sender, EventArgs e)
        {
            Response.Cookies[
"MyCook"].Domain = ".local.com";
        }

   这样,我们所有的二级域全部是认这一个主域的,比如a.local.com;b.local.com;user.local.com等等。有了这个认识,我想大家心里也有数了,该怎么怎么做,但是现在问题是用来生成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 = ".local.com";
        }

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

我们还有一个外题问题,就是客户端保存的问题解决了,但是服务器端的Session怎么办?一般情况下我们不同的子域做的是指向不同的服务器的,比如user.local.com 专门一台服务器,yellow.local.com专门一台服务器。这时它们别说是进程了,连物理上都不是一个了。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" />