這個唯一的SessionId還是有很大的實際意義,當一個用戶提交表單時,瀏覽器就會將用戶的SessionId自動附加在HTTP頭信息中,當服務器 處理完這個表單后,就會將結果返回給SessionId所對應的用戶。
如下是Web.config如何配置Session的:
<configuration>
<system.web>
<sessionState mode=" Off | InProc | StateServer | SQLServer "
cookieless=" true | false "
timeout=" number of minutes "
stateConnectionString=" tcpip=server:port "
sqlConnectionString=" sql connection string "
stateNetworkTimeout=" number of seconds " />
</system.web>
</configuration>
其中各個節點屬性:
mode: Session的存儲方式(必有的屬性)。
InProc:將Session存到進程內(這是Default值。)
off:禁用Session.
StateServer:將Session存到獨立的狀態服務中(Asp.net State Service).
SqlServer:將Session存到SqlServer中。
Cookieless:設置客戶端Session存儲的方式。
false:使用Cookie模式(default).
true:使用Cookieless模式。
timeout:設置Session過期時間(default is 20 minutes)
stateConnectionString: 設置Session獨立存放的狀態服務所在服務器的名稱(地址)和端口號,當mode=“stateserver時,這個屬性就是必 須的。
sqlConnectionString:設置與Sqlserver的連接字符串,當mode="sqlserver"時,這個屬性時必須的。
stateNetWorkTimeout:設置當mode=“StateServer”時,經過多少秒空閑后, 斷開web服務器與存儲狀態信息服務器的TCP/IP連接(default is 10 seconds).
asp.net中客戶端Session的存儲。
asp.net中,默認是使用Cookie存儲Session的,如果是將cookieless="false",改成 cookieless="true",則session就不用cookie來存儲了,而是使用url來存儲。
asp.net服務器端session存儲在進程內(inproc)
當mode="Inproc"時,服務器的Session存儲在IIS進程中,當IIS關閉,重啟時,這些Session信息就會丟失,但這種模式最大的 好處就是性能提高。
asp.net服務器端Session存儲在進程外(StateServer)
當mode="StateServer"時,服務器的Session就存儲在"ASP.NET State Server"這個服務的進程中,在服務中找到名為:“ASP.NET State Service”的服務,啟動這個服務,在資源管理器的進程中就能找到一個名 為:“aspnet_state.exe"的進程,這個就是我們保存 Session的進程。
”ASP.NET State Server"服務可以與Web服務器分開.eg:web服務器在192.168.0.100上,“asp.net state service"服務在192.168.0.101上,則可以進行設置:
mode="StateServer" stateConnection="tcpip=192.168.1.101:42424".
asp.net服務器端Session存儲到SQLServer中(SQLServer),
當mode="sqlserver"時,服務器的Session就是存儲到Sql server中建立一個存儲Session的數據庫。在
%windir%\Microsoft.NET\Framework\v2.0.50727 下有個名為: InstallSqlState.sql 的sql腳本文件. 這個腳本是專門用來建存儲Session的數據庫以及一個維護Session信息數據庫的SQL Server代理作業的.
執行此sql腳本后,會看到一個新增的aspstate數據庫,但這個數據庫中,只有存儲過程,沒有用戶表,用戶表放到了tempdb這個數據庫中去 了,ASpstateTempSessions和ASPStateTempApplications,Session信息存儲到了 ASPStateTempApplication存儲了asp中Application對象信息。
另外查看管理->SQL Server代理->作業,會發現多了一個名為:
ASPState_job_DeleteExpiredSession的作業,這個作業實際上是每分鍾去ASPStateTempSession中 刪除過期的Session信息。
上面的方法是建立Session數據庫的一個”官方“方法,但在實際的應用中一般沒這么去建,而是采用另一種方法,使用下面這段命令來自動創建 Session數據庫:
aspnet_regsql.exe -S ServerName\InstanceName -U User -P Password -d DBName -ssadd -sstype c
此命令將在ServerName\InstanceName建立DBName的數據庫, 用戶存儲Session的數據庫. 此數據庫中包含了存儲過程和用戶表. 同時在SQL Server代理 -> 作業 中也加入了相應的作業.
然后在Web.config中設置好配置信息:
mode="SQLServer" sqlConnectionString="data source=ServerName\InstanceName; Integrated Security=SSPI;"
"Integrated Security=SSPI;" 是指使用Windows集成身份驗證.
如果使用SQL用戶登陸方式. 則在sqlConnectionString中設置好"userid=sa; password=***".
這樣一來就可以將Session存放到SQLServer中了
不得不說當我了解了session的原理之后感覺到了驚訝,因為session竟然是基於cookie的,所以當一向被認為不安全的cookie和超安全的session等同之后確實很讓人接受不了,因為我確實是菜鳥
做了這么多年的web,用了這么多年的session和cookie,竟然就習慣了這兩個東西,把他們的功能當成了天然的功能,從來沒有考慮過他們的原理,實在是悲哀,直到有一天,我覺醒了。。
首先應該了解http協議的請求過程,這個以前倒是知道,當然是基於tcp/ip協議,客戶端請求服務器,服務器回答客戶端,無狀態的,那么服務器如何區分客戶端的呢?看完本文自然明白了
關於cookie
先來說cookie,怎么使用就不說了,cookie按照在客戶端存放的方式,可以分為兩類,
一種是會話性質的cookie,存放在瀏覽器內存中,當你在用代碼向客戶端寫入cookie的時候,如果沒有指定過期時間,那么cookie是存放在瀏覽器的內存里面的,不會持久化在硬盤上,也就是你在瀏覽器的臨時文件里找不到!
一種是持久化的cookie,存放在硬盤上,當你指定了cookie的過期時間,那么,在客戶端寫入cookie的時候就會在瀏覽器的臨時文件下生成一個文件,具體格式和名字可以到瀏覽器臨時文件去看下
cookie的原理是這樣的:當你在服務器端的代碼里寫了response.cookie["mycookie"]="mytestcookie"的時候,返回給客戶端的http響應中,會在http相應頭中加入cookie的信息,瀏覽器收到相應后,會按照http響應頭里的cookie在客戶端建立cookie。
客戶端的cookie也是插在http頭中發送到服務器端的,並且,一個域,在客戶端建立的所有cookie,在客戶端的每一次的http請求都會帶着,比如testwebsite.com這個站點,任何時刻寫到客戶端的cookie,只要不過期,瀏覽器在向testwebsite.com發送http請求的時候,會帶上這些cookie,所以cookie在客戶端的大小是有限制的
關於session
cookie明白了之后session就容易理解了,asp的session和asp.net默認的session就是通過第一種cookie來實現的,你可以把自己的瀏覽器的cookie徹底禁用,然后再去登錄一些注冊過的門戶網站,會發現很多都登錄不了了。是cookie,將http的請求變得有狀態。session的實現是web服務器的事情,不過很顯然是利用會話cookie,也就是存放在瀏覽器內存里的那種cookie來實現的,在cookie里只是存放了SessionID,然后在服務器上建立了一張表,對應客戶端的SessionID。這張表是存放在服務器上的進程中的,也就是服務器的內存里,也就是Application里。當客戶端請求服務器的時候,如果服務器發現這是一個新的請求,就會分配給他一個SessionID,也就是在瀏覽器寫入一個sessionID的cookie。你可以試一下,在你請求過一次服務器之后,在服務器遍歷客戶端所有的cookie,就會發現這個叫做SessionID的cookie。
所以在了解了這個session的原理之后我們可以自己來造一個自己的session,過程就不說了。
那么我們現在可以說session就是依賴於會話性的cookie的
關於session的其他
asp.net可以定制session的實現方式,默認是上面說的原理,但是可以改變的。
可以選擇不依賴於cookie,就是把sessionID作為URL的一部分放在每一次的請求后面,像這樣:
http://www.testwebsite.com/(-此處為一串sessionID的字符串-)/test.aspx
但是這種方式你如果在html中指定url的時候,指定了絕對路徑,比如
<a href="http://www.testwebsite.com/other.aspx">test</a>
那么點擊這個鏈接就會不是同一個會話了,因為此時區分客戶端的唯一標志就是域名后面那串字符串
php也有類似的做法,不依賴cookie的做法是在get的參數里面帶一個sessionID的參數
asp.net還可以定義session里存放數據的存儲位置,放在其他進程,放在sqlServer中等等,知道了session的原理就很容易明白,我們可以自己就可以造一個類似session作用的東西的
session的結束問題
還有知道了session的原理就會明白一個session會話如何結束,除非服務器端可以清除一個session會話,客戶端是沒有能力清除session的,關閉瀏覽器的時候並不能夠結束當前的會話(忽略瀏覽器關閉事件),在不依賴於cookie的session中最明顯,你可以記下你的sessionID那串字符串,關閉瀏覽器,打開,把sessionID自己替換,你就可以恢復剛才的會話了。所謂的20分鍾session超時,是服務器每隔20分鍾對於不活動的session清除而已。
還有要指出的是依賴於cookie的session是存放在瀏覽器內存中的,所以一個瀏覽器的進程就會產生一個session,可以通過任務管理器查看進程,對於IE來說,只有雙擊桌面上的瀏覽器快捷方式才能新啟動一個進程的,當然其他類似啟動iexplorer.exe的行為也可以
到這里你會發現在依賴於cookie的session中,是需要瀏覽器的支持的!所以當你不用瀏覽器而自己來制造http請求的時候,session就用了!
對於js的ajax請求,確切的說是xmlhttp這個組件發送的http請求,雖然是你使用js的代碼自己制造的,但是依然是借助於瀏覽器發送的,所以可以獲得session。
所以在webservice中使用session我們還得自己造一個東西實現cookie的功能
如果你使用InProc模式的Session,存儲過多的數據會導致IIS進程被回收,引發Session不斷丟失。
· 如果你使用StateServer存儲Session,那么數據在存入Session以前需要進行序列化,序列化會消耗大量的CPU資源。
· 如果你使用SqlServer模式的Session,數據不但要序列化而且還是存儲在磁盤上,更不適合存儲大量數據。
SessionID是一個由24個字符組成的隨機字符串
ookie是否開啟不影響Session使用,缺點是不能再使用絕對鏈接了。
stateNetworkTimeout屬性表示從狀態服務器請求Session數據最長的時間,默認為10秒,如果網絡連接不是很好,請把這個數字適當設置得大一點。
只有把對象標注為可序列化后才能在服務中進行存儲。什么是序列化呢?序列化是指將對象實例的狀態存儲到存儲媒體的過程。在此過程中,先將對象的公共字段和私有字段以及類的名稱轉換為字節流,然后再把字節流寫入數據流。在隨后對對象進行反序列化時,將創建出與原對象完全相同的副本。要使一個類可序列化,最簡單的方法是使用 Serializable 屬性對它進行標記。
因此Session能存儲的類型為: 對於InProc模式是一切類型,而對於StateServer和SqlServer模式是一切可以序列化的類型。
一定程度上反映了Session是不能跨應用程序的。舉例來說,我們在計算機上建立了兩個網站,同時都使用Session[“UserName”]來保存登錄的用戶名,一個網站的用戶登錄后,另一個網站直接訪問Session[“UserName”]是取不到任何值的。那么,Session是否可以跨用戶呢?通過前面的分析我們知道,肯定是不行的,Session通過SessionID來區分用戶,一般來說SessionID是不可能出現重復的現象,也就是說Session一般是不會“串號”的。既然頁面每次提交的時候都會附加上當前用戶的SessionID,那么Session應該是可以跨頁面的,也就是說一個網站中所有的頁面都使用同一份Session。你可以自己來做個試驗,請讀者打開剛才那個頁面,然后按Ctrl+N組合鍵再打開第二個同樣的頁面,單擊第一個頁面中的“寫入Session”按鈕,單擊第二個頁面中的“讀取Session”按鈕,可以發現Session的值被正確讀出了。第三個問題的答案有了。
表12.1 三種模式的Session比較
InProc |
StateServer |
SQLServer |
|
存儲物理位置 |
IIS進程(內存) |
Windows服務進程(內存) |
SQLServer數據庫(磁盤) |
存儲類型限制 |
無限制 |
可以序列化的類型 |
可以序列化的類型 |
存儲大小限制 |
無限制 |
||
使用范圍 |
當前請求上下文,對於每個用戶獨立 |
||
生命周期 |
第一次訪問網站的時候創建Session超時后銷毀 |
||
優點 |
性能比較高 |
Session不依賴Web服務器,不容易丟失 |
|
缺點 |
容易丟失 |
序列化與反序列化消耗CPU資源 |
序列化與反序列化消耗CPU資源,從磁盤讀取Session比較慢 |
使用原則 |
不要存放大量數據 |
· 為什么當我設置cookieless為true后,在重定向的時候會丟失Session?
n 當使用cookieless時,你必須使用相對路徑替換程序中的絕對路徑,如果使用絕對路徑,ASP.NET將無法在URL中保存SessionID。
為什么每次請求的SessionID都不相同?
n 可能是沒有在Session里面保存任何信息引起的,即程序中任何地方都沒有使用Session。只有在Session中保存了內容后,Session才會和瀏覽器進行關聯,此時的SessionID將不會再變化
打開iecookiesview,這款軟件是拿來察看和修改本機的cookies的,很方便我們的cookies欺騙入侵。
在iecookiesview 里找到你要欺騙的那個網站,看到了嗎?有你的用戶名和md5加密的密碼,我們吧這兩項改為管理員的,就是把剛才數據庫里面的管理員賬號和md5加密的密碼代替你自己的。點擊“更改cookies”,打開一個新的ie,然后再去訪問那個論壇,看到沒有?你現在已經是管理員了。
接着,麻煩的事出現了,后台登陸並不是以cookies來實現的,而是以session實現的 ,所以我們同樣來欺騙session