天天看點

JavaEE 要懂的小事:三、圖解Session(會話)一、Session由來二、Session機制三、詳細介紹Seesion機制過程四、補充五、總結

http的無狀态,也就是說,每次請求都是獨立的線程。舉個例子吧:購物中,你選擇了a商品,加入購物車,這就是a線程。然後在選擇b商品就是b線程。可是每次線程獨立(對容器而言,a、b成了不同的使用者),線程a不知道有b,b也不知道a。如何一起付款呢?

簡答來說:怎麼儲存同個使用者多個請求會話狀态呢?自然https保證連接配接是安全的,可以使它與一個會話關聯。

問題就在于如何跟蹤同一個使用者,選擇自然很多:

1、ejb(有狀态會話bean儲存會話狀态) 環境苛刻需要帶ejb的j2ee伺服器,而不是tomcat這種web容器。 2、資料庫(這貌似萬能的。針對資料) 3、就是我們要講的httpseesion,儲存跨一個特定使用者多個請求的會話狀态。 4、上面說的https,條件太苛刻了。
JavaEE 要懂的小事:三、圖解Session(會話)一、Session由來二、Session機制三、詳細介紹Seesion機制過程四、補充五、總結

機制,什麼用詞有點高大上。其實就是把它内在的一點東西說出來。主要兩個w:what?how?

what is session?

session代表着伺服器和用戶端一次會話的過程。直到session失效(服務端關閉),或者用戶端關閉時結束。

how does session works?

session 是存儲在服務端的,并針對每個用戶端(客戶),通過sessionid來差別不同使用者的。session是以cookie技術或url重寫實作。預設以cookie技術實作,服務端會給這次會話創造一個jsessionid的cookie值。

補充:

其實還有一種技術:表單隐藏字段。它也可以實作session機制。這裡隻是作為補充,伺服器響應前,會修改form表單,添加一個sessionid類似的隐藏域,以便傳回服務端的時候可以标示出此會話。 這技術,也可以使用在web安全上,可以有效地控制crsf跨站請求僞造。
JavaEE 要懂的小事:三、圖解Session(會話)一、Session由來二、Session機制三、詳細介紹Seesion機制過程四、補充五、總結

圖中這是session第一次請求的詳細圖。以cookie技術實作,我也寫了個httpsessionbycookieservlett.java 的servlet小demo,模拟下seesion的一生。代碼如下:

<a href="http://www.bysocket.com/?p=384#">?</a>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

<code>package</code> <code>org.servlet.sessionmngmt;</code>

<code>import</code> <code>java.io.ioexception;</code>

<code>import</code> <code>java.io.printwriter;</code>

<code>import</code> <code>javax.servlet.servletexception;</code>

<code>import</code> <code>javax.servlet.annotation.webservlet;</code>

<code>import</code> <code>javax.servlet.http.httpservlet;</code>

<code>import</code> <code>javax.servlet.http.httpservletrequest;</code>

<code>import</code> <code>javax.servlet.http.httpservletresponse;</code>

<code>import</code> <code>javax.servlet.http.httpsession;</code>

<code>/*</code>

<code> </code><code>* copyright [2015] [jeff lee]</code>

<code> </code><code>*</code>

<code> </code><code>* licensed under the apache license, version 2.0 (the "license");</code>

<code> </code><code>* you may not use this file except in compliance with the license.</code>

<code> </code><code>* you may obtain a copy of the license at</code>

<code> </code><code>* unless required by applicable law or agreed to in writing, software</code>

<code> </code><code>* distributed under the license is distributed on an "as is" basis,</code>

<code> </code><code>* without warranties or conditions of any kind, either express or implied.</code>

<code> </code><code>* see the license for the specific language governing permissions and</code>

<code> </code><code>* limitations under the license.</code>

<code> </code><code>*/</code>

<code>/**</code>

<code> </code><code>* @author jeff lee</code>

<code> </code><code>* @since 2015-7-12 10:58:28</code>

<code> </code><code>*  httpsession的預設cookie實作案例</code>

<code>@webservlet</code><code>(urlpatterns =</code><code>"/sessionbycookie"</code><code>)</code>

<code>public</code> <code>class</code> <code>httpsessionbycookieservlett</code><code>extends</code> <code>httpservlet {</code>

<code>    </code><code>private</code> <code>static</code> <code>final</code> <code>long</code> <code>serialversionuid = 1l;</code>

<code>    </code><code>@override</code>

<code>    </code><code>protected</code> <code>void</code> <code>doget(httpservletrequest req, httpservletresponse resp)</code>

<code>            </code><code>throws</code> <code>servletexception, ioexception {</code>

<code>        </code> 

<code>        </code><code>// 擷取session</code>

<code>        </code><code>// 如果是第一次請求的話,會建立一個httpseesion,等同于 req.getsession(true);</code>

<code>        </code><code>// 如果已存在session,則會擷取session。</code>

<code>        </code><code>httpsession session = req.getsession();</code>

<code>        </code><code>if</code> <code>(session.isnew()) {</code>

<code>            </code><code>// 設定session屬性值</code>

<code>            </code><code>session.setattribute(</code><code>"name"</code><code>,</code><code>"jeff"</code><code>);</code>

<code>        </code><code>}</code>

<code>        </code><code>// 擷取sessionid</code>

<code>        </code><code>string sessionid = session.getid();</code>

<code>        </code><code>printwriter out = resp.getwriter();</code>

<code>        </code><code>// 如果httpseesion是建立的話</code>

<code>            </code><code>out.println(</code><code>"hello,httpsession! &lt;br&gt;the first response - seesionid="</code>

<code>                    </code><code>+ sessionid +</code><code>" &lt;br&gt;"</code><code>);</code>

<code>        </code><code>}</code><code>else</code> <code>{</code>

<code>            </code><code>out.println(</code><code>"hello,httpsession! &lt;br&gt;the second response - seesionid="</code>

<code>            </code><code>// 從session擷取屬性值</code>

<code>            </code><code>out.println(</code><code>"the second-response - name: "</code>

<code>                    </code><code>+ session.getattribute(</code><code>"name"</code><code>));</code>

<code>    </code><code>}</code>

<code>    </code> 

<code>}</code>

隆重打個小廣告:

① 用戶端向服務端發送第一次請求

此時,用戶端想讓服務端把自己的名字設定到會話中。

② 服務端的容器産生該使用者唯一sessionid的session對象,并設定值

可以從代碼中看出通過從請求中req.getsession(),新生成了一個session對象。并設定了setattribute(“name”, “jeff”),key為string,value是對象皆可。

這時候,我們不用再把session通過cookie技術處理,容器幫我們處理了。

③ 容器響應 set-cookie:jsessionid= …

我們可以f12,檢視此次響應。

JavaEE 要懂的小事:三、圖解Session(會話)一、Session由來二、Session機制三、詳細介紹Seesion機制過程四、補充五、總結

從圖中可得到,每個cookie的set,都有一個對應set-cookie的頭。httponly可是此cookie隻讀模式。隻不過session唯一辨別是:jsessionid

④ 浏覽器解析cookie,儲存至浏覽器檔案。

JavaEE 要懂的小事:三、圖解Session(會話)一、Session由來二、Session機制三、詳細介紹Seesion機制過程四、補充五、總結

第二次請求會發什麼變化呢?

JavaEE 要懂的小事:三、圖解Session(會話)一、Session由來二、Session機制三、詳細介紹Seesion機制過程四、補充五、總結

下面,泥瓦匠重新通路了這個位址:

① 再次請求

JavaEE 要懂的小事:三、圖解Session(會話)一、Session由來二、Session機制三、詳細介紹Seesion機制過程四、補充五、總結

此時,請求會有cookie值:jsessionid=… 該值傳給服務端

② 容器擷取sessionid

,關聯httpsession

③ 此時響應無setcookie

如圖:

JavaEE 要懂的小事:三、圖解Session(會話)一、Session由來二、Session機制三、詳細介紹Seesion機制過程四、補充五、總結

但是這次請求,我們響應出上一次請求set的值。jeff 就列印出來了!

關于服務端擷取session,也就是從請求中擷取session對象,容器會幫你根據cookie找到唯一的session對象。

泥瓦匠記憶小抄:seesion機制,記住兩次請求圖即可。

點到為止哈~ 以後詳細寫。此圖來自網絡

JavaEE 要懂的小事:三、圖解Session(會話)一、Session由來二、Session機制三、詳細介紹Seesion機制過程四、補充五、總結

上圖bad guy,就是攻擊者。跨站請求僞造,僞造使用者請求來對伺服器資料或者是使用者等造成威脅。web安全也就是從這些基礎中慢慢提升。

1、大概地描述了session的工作機制,和一些安全相關。記住seesion是什麼,怎麼用,在服務端用戶端之間怎麼傳輸即可。