九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Tomcat中的Session小結(jié)

什么是Session

對Tomcat而言,Session是一塊在服務(wù)器開辟的內(nèi)存空間,其存儲結(jié)構(gòu)為ConcurrentHashMap;

Session的目的

Http協(xié)議是一種無狀態(tài)協(xié)議,即每次服務(wù)端接收到客戶端的請求時,都是一個全新的請求,服務(wù)器并不知道客戶端的歷史請求記錄;

Session的主要目的就是為了彌補Http的無狀態(tài)特性。簡單的說,就是服務(wù)器可以利用session存儲客戶端在同一個會話期間的一些操作記錄;

實現(xiàn)機制

先看兩個問題,如下:

1、服務(wù)器如何判斷客戶端發(fā)送過來的請求是屬于同一個會話?

答:用Session id區(qū)分,Session id相同的即認為是同一個會話,在Tomcat中Session id用JSESSIONID表示;

2、服務(wù)器、客戶端如何獲取Session id?Session id在其之間是如何傳輸?shù)哪兀?/strong>

答:服務(wù)器第一次接收到請求時,開辟了一塊Session空間(創(chuàng)建了Session對象),同時生成一個Session id,并通過響應(yīng)頭的Set-Cookie:“JSESSIONID=XXXXXXX”命令,向客戶端發(fā)送要求設(shè)置cookie的響應(yīng);

客戶端收到響應(yīng)后,在本機客戶端設(shè)置了一個JSESSIONID=XXXXXXX的cookie信息,該cookie的過期時間為瀏覽器會話結(jié)束;

接下來客戶端每次向同一個網(wǎng)站發(fā)送請求時,請求頭都會帶上該cookie信息(包含Session id);

然后,服務(wù)器通過讀取請求頭中的Cookie信息,獲取名稱為JSESSIONID的值,得到此次請求的Session id;

ps:服務(wù)器只會在客戶端第一次請求響應(yīng)的時候,在響應(yīng)頭上添加Set-Cookie:“JSESSIONID=XXXXXXX”信息,接下來在同一個會話的第二第三次響應(yīng)頭里,是不會添加Set-Cookie:“JSESSIONID=XXXXXXX”信息的;

而客戶端是會在每次請求頭的cookie中帶上JSESSIONID信息;

舉個例子:

以chrome瀏覽器為例,訪問一個基于tomcat服務(wù)器的網(wǎng)站的時候,

瀏覽器第一次訪問服務(wù)器,服務(wù)器會在響應(yīng)頭添加Set-Cookie:“JSESSIONID=XXXXXXX”信息,要求客戶端設(shè)置cookie,如下圖:

同時我們也可以在瀏覽器中找到其存儲的sessionid信息,如下圖

接下來,瀏覽器第二次、第三次...訪問服務(wù)器,觀察其請求頭的cookie信息,可以看到JSESSIONID信息存儲在cookie里,發(fā)送給服務(wù)器;且響應(yīng)頭里沒有Set-Cookie信息,如下圖:

只要瀏覽器未關(guān)閉,在訪問同一個站點的時候,其請求頭Cookie中的JSESSIONID都是同一個值,被服務(wù)器認為是同一個會話。

 再舉個簡單的例子加深印象,新建個Web工程,并寫一個Servlet,在doGet中添加如下代碼,主要做如下工作

首先,從session中獲取key為count的值,累加,存入session,并打?。?/p>

然后,每次從請求中獲取打印cookie信息,從響應(yīng)中獲取打印Header的Set-Cookie信息:

    /**     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)     */    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {                if(request.getSession().getAttribute("count") == null){            request.getSession().setAttribute("count", 0);            response.getWriter().write(0+"");        }else{            int a = Integer.parseInt(request.getSession().getAttribute("count").toString());            request.getSession().setAttribute("count", ++a);            response.getWriter().write(a+"");        }        Cookie[] cookies = request.getCookies();        StringBuffer sb = new StringBuffer();        if(cookies!=null){            for(Cookie cookie : cookies){                sb.append(cookie.getName()+":"+cookie.getValue()+",");            }            sb.deleteCharAt(sb.length()-1);        }        System.out.println("[第"+(++index)+"次訪問]from client request, cookies:" + sb);        System.out.println("[第"+(index)+"次訪問]from server response, header-Set-Cookie:" + response.getHeader("Set-Cookie"));;    }

部署到tomcat后,連續(xù)訪問該servlet,觀察控制臺輸出,如下,客戶端第一次訪問服務(wù)器的時候,在服務(wù)端的響應(yīng)頭里添加了JSESSIONID信息,且接下來客戶端的每次訪問都會帶上該JSESSIONID:

其實這里有一個問題,session劫持

只要用戶知道JSESSIONID,該用戶就可以獲取到JSESSIONID對應(yīng)的session內(nèi)容,還是以上面這個例子為例,

我先用IE瀏覽器訪問該站點,比如連續(xù)訪問了5次,此時,session中的count值為:

查看該會話的Session id,為6A541281A79B24BC290ED3270CF15E32

接下來打開chrome控制臺,將IE瀏覽器獲取過來的JSESSIONID信息(“6A541281A79B24BC290ED3270CF15E32”)寫入到cookie中,如下

接著刪除其中的一個,只留下JSESSIONID為“6A541281A79B24BC290ED3270CF15E32”的cookie;

刷新頁面,發(fā)現(xiàn)我們從session獲取的count值已經(jīng)變成6了,說明此次chrome瀏覽器的請求劫持了IE瀏覽器會話中的session,

Tomcat中的session實現(xiàn)

Tomcat中一個會話對應(yīng)一個session,其實現(xiàn)類是StandardSession,查看源碼,可以找到一個attributes成員屬性,即存儲session的數(shù)據(jù)結(jié)構(gòu),為ConcurrentHashMap,支持高并發(fā)的HashMap實現(xiàn);

    /**     * The collection of user data attributes associated with this Session.     */    protected Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();

那么,tomcat中多個會話對應(yīng)的session是由誰來維護的呢?ManagerBase類,查看其代碼,可以發(fā)現(xiàn)其有一個sessions成員屬性,存儲著各個會話的session信息:

    /**     * The set of currently active Sessions for this Manager, keyed by     * session identifier.     */    protected Map<String, Session> sessions = new ConcurrentHashMap<String, Session>();

接下來,看一下幾個重要的方法,

服務(wù)器查找Session對象的方法

客戶端每次的請求,tomcat都會在HashMap中查找對應(yīng)的key為JSESSIONID的Session對象是否存在,可以查看Request的doGetSession方法源碼,如下源碼:

View Code

先看doGetSession方法中的如下代碼,這個一般是第一次訪問的情況,即創(chuàng)建session對象,session的創(chuàng)建是調(diào)用了ManagerBase的createSession方法來實現(xiàn)的; 另外,注意response.addSessionCookieInternal方法,該方法的功能就是上面提到的往響應(yīng)頭寫入“Set-Cookie”信息;最后,還要調(diào)用session.access方法記錄下該session的最后訪問時間,因為session是可以設(shè)置過期時間的;

        session = manager.createSession(sessionId);        // Creating a new session cookie based on that session        if ((session != null) && (getContext() != null)               && getContext().getServletContext().                       getEffectiveSessionTrackingModes().contains(                               SessionTrackingMode.COOKIE)) {            Cookie cookie =                ApplicationSessionCookieConfig.createSessionCookie(                        context, session.getIdInternal(), isSecure());            response.addSessionCookieInternal(cookie);        }        if (session == null) {            return null;        }        session.access();        return session;

再看doGetSession方法中的如下代碼,這個一般是第二次以后訪問的情況,通過ManagerBase的findSession方法查找session,其實就是利用map的key從ConcurrentHashMap中拿取對應(yīng)的value,這里的key即requestedSessionId,也即JSESSIONID,同時還要調(diào)用session.access方法,記錄下該session的最后訪問時間;

        if (requestedSessionId != null) {            try {                session = manager.findSession(requestedSessionId);            } catch (IOException e) {                session = null;            }            if ((session != null) && !session.isValid()) {                session = null;            }            if (session != null) {                session.access();                return (session);            }        }

在session對象中查找和設(shè)置key-value的方法

這個我們一般調(diào)用getAttribute/setAttribute方法:

getAttribute方法很簡單,就是根據(jù)key從map中獲取value;

setAttribute方法稍微復(fù)雜點,除了設(shè)置key-value外,如果添加了一些事件監(jiān)聽(HttpSessionAttributeListener)的話,還要通知執(zhí)行,如beforeSessionAttributeReplaced, afterSessionAttributeReplaced, beforeSessionAttributeAdded、 afterSessionAttributeAdded。。。

session存在的問題

  • 安全性,session劫持,這個前面已經(jīng)舉過例子了;
  • 增加服務(wù)器壓力,因為session是直接存儲在服務(wù)器的內(nèi)存中的;
  • 如果存在多臺服務(wù)器的話,還存在session同步問題,當(dāng)然如果只有一臺tomcat服務(wù)器的話,也就沒有session同步的事情了,然而現(xiàn)在一般的應(yīng)用都會用到多臺tomcat服務(wù)器,通過負載均衡,同一個會話有可能會被分配到不同的tomcat服務(wù)器,因此很可能出現(xiàn)session不一致問題;解決session同步問題,實際上主要是保證能夠抽離出一塊共享空間存放session信息,且這塊空間不同的tomcat服務(wù)器都可以訪問到;一般這塊共享的空間可以是數(shù)據(jù)庫,或者某臺服務(wù)器的內(nèi)存空間,甚至硬盤空間,或者客戶端的cookie也是可以的;
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
生活服務(wù)
熱點新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服