1. 程式人生 > >Session 儲存方式

Session 儲存方式

 

  簡單來說,Session就是伺服器給客戶端的一個編號,當一臺web伺服器執行時,可能 是有多個使用者都在瀏覽這臺伺服器上的網站,當每個使用者首次與這臺伺服器建立連線時,它就與這個伺服器建立了一個Session,同時伺服器就會自動為其分 配一個SessionId,用以標識這個使用者的唯一身分,這個Session就是有伺服器隨機產生的一個由24個字元組成的字串。

         這個唯一的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=&ldquo;stateserver時,這個屬性就是必 須的。
sqlConnectionString:設定與Sqlserver的連線字串,當mode="sqlserver"時,這個屬性時必須的。
stateNetWorkTimeout:設定當mode=&ldquo;StateServer&rdquo;時,經過多少秒空閒後, 斷開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"這個服務的程序中,在服務中找到名為:&ldquo;ASP.NET State Service&rdquo;的服務,啟動這個服務,在資源管理器的程序中就能找到一個名 為:&ldquo;aspnet_state.exe"的程序,這個就是我們儲存 Session的程序。
&rdquo;ASP.NET State Server"服務可以與Web伺服器分開.eg:web伺服器在192.168.0.100上,&ldquo;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中了

開發者小組,歡迎大家加入http://home.cnblogs.com/group/msdn2/ net技術QQ群號:21386099 有問題的可以在小組提問  

不得不說當我瞭解了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

  簡單來說,Session就是伺服器給客戶端的一個編號,當一臺web伺服器執行時,可能 是有多個使用者都在瀏覽這臺伺服器上的網站,當每個使用者首次與這臺伺服器建立連線時,它就與這個伺服器建立了一個Session,同時伺服器就會自動為其分 配一個SessionId,用以標識這個使用者的唯一身分,這個Session就是有伺服器隨機產生的一個由24個字元組成的字串。

         這個唯一的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=&ldquo;stateserver時,這個屬性就是必 須的。
sqlConnectionString:設定與Sqlserver的連線字串,當mode="sqlserver"時,這個屬性時必須的。
stateNetWorkTimeout:設定當mode=&ldquo;StateServer&rdquo;時,經過多少秒空閒後, 斷開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"這個服務的程序中,在服務中找到名為:&ldquo;ASP.NET State Service&rdquo;的服務,啟動這個服務,在資源管理器的程序中就能找到一個名 為:&ldquo;aspnet_state.exe"的程序,這個就是我們儲存 Session的程序。
&rdquo;ASP.NET State Server"服務可以與Web伺服器分開.eg:web伺服器在192.168.0.100上,&ldquo;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中了