久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

深入探討Session

 oldzhoua 2019-03-14

作者:千里明月

my.oschina.net/u/3490860/blog/2986928

簡介

session(會話),其實是一個容易讓人誤解的詞,。它總跟web系統(tǒng)的會話掛鉤,,利用session,,javaweb項目實現(xiàn)了登錄狀態(tài)的控制。坊間流傳,,關(guān)閉瀏覽器,,就是關(guān)閉了web系統(tǒng)的會話。

其實瀏覽器對于會話有自己的定義,,而web系統(tǒng)對于會話也有自己的定義,。在tomcat中,session通常是指實現(xiàn)了HttpSession接口的實現(xiàn)類,。并且不存在關(guān)閉瀏覽器就會關(guān)閉tomcat的HttpSession這種狀況,。

session本身并不難,如果只是做登錄校驗之類的功能,,并不需要深入了解,但難的是session和cookie的結(jié)合使用,,在不同情況下瀏覽器對cookie的控制行為所涉及到的諸多細節(jié),,我搜查了很多資料,查看過tomcat源碼,,亦是沒有找到全面的概述,。

當然我并未看過、也不知道去哪里看比較全面的關(guān)于瀏覽器對cookie的控制資料,,如果有知道的大神,,還望留言鏈接。本文題目,,之所以說是探討,,而不是了解或者介紹,因為我自己也卡在了某個點上,,由于時間關(guān)系,,我不能花太多時間去研究,但又不忍心就此放棄,,所以先記錄下來,,日后有機會再研究,這期間如有大神指點,,也許能讓我茅塞頓開,。

session本質(zhì)

我用的是javaweb項目,因此這里的session特指HttpSession,。先來看下tomcat源碼中對session的設(shè)計,,在org.apache.catalina.session包下,有如下設(shè)計:

平時所用到的HttpSession的實現(xiàn)類就是這個standardSession,。但是所獲取的HttpSession實例確是外觀類StandardSessionFacade,,其屏蔽了許多方法,,但也增強了安全性。

HttpSession提供了一些方法,,來控制session或者獲取session的狀態(tài),,如獲取session的id,獲取session的創(chuàng)建時間,,設(shè)置session的attribute,,使session失效等。值得一提的是session的attribute其實是一個線程安全的hashMap:

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

但是,,創(chuàng)建session,、根據(jù)id獲取session的方法并不在這里,而是在一個管理器中,,其設(shè)計如下:

ManagerBase是實現(xiàn)了Manager接口的抽象類,,實現(xiàn)了管理session的功能。其實現(xiàn)子類PersistentManagerBase拓展了將session持久化的功能,。但是這里不需要講到其子類,。看ManagerBase中的一段代碼:

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

由此可知,,所謂的session,,其實就是一個用線程安全的hashMap存儲起來的實現(xiàn)了Session接口的standardSession對象,在hashmap中以其id為key,,自身為value,。

再看獲取session的方法,一目了然:

    @Override
    public Session findSession(String id) throws IOException {
        if (id == null) {
            return null;
        }
        return sessions.get(id);
    }

最重要的是看其createSession方法:

 @Override
    public Session createSession(String sessionId) {

        if ((maxActiveSessions >= 0) &&
                (getActiveSessions() >= maxActiveSessions)) {
            rejectedSessions++;
            throw new TooManyActiveSessionsException(
                    sm.getString('managerBase.createSession.ise'),
                    maxActiveSessions);
        }

        // Recycle or create a Session instance
        Session session = createEmptySession();

        // Initialize the properties of the new session and return it
        session.setNew(true);
        session.setValid(true);
        session.setCreationTime(System.currentTimeMillis());
        session.setMaxInactiveInterval(getContext().getSessionTimeout() * 60);
        String id = sessionId;
        if (id == null) {
            id = generateSessionId();
        }
        session.setId(id);
        sessionCounter++;

        SessionTiming timing = new SessionTiming(session.getCreationTime(), 0);
        synchronized (sessionCreationTiming) {
            sessionCreationTiming.add(timing);
            sessionCreationTiming.poll();
        }
        return session;
    }

這個方法是在什么時候調(diào)用的呢,?當瀏覽器訪問系統(tǒng)時,,request會解析請求中攜帶的jssesionid,用它去找到存在于應(yīng)用中的session,,但是如果沒有找到,,那么就會調(diào)用session的創(chuàng)建方法,并且生成一個新的jssessionid,,返回session,。

總而言之,session是存在于線程安全的map中的值,,可以通過id找到,,也可以使用invalidate方法銷毀,但絕不會是瀏覽器關(guān)閉,,就能對它進行銷毀的。

cookie簡介

提到session,,那么cookie是不得不說的,。至于cookie是什么,,我就不多說了,大家都懂,。直接看其內(nèi)容吧:

這是一次http請求中(http://localhost:8080/test1),,包含的請求和響應(yīng)信息,是對一個系統(tǒng)的初次訪問,,用的是谷歌瀏覽器,。

請求頭中,包含的Cookie信息,,并沒有上文提到的jsessionid, 那是因為這是對系統(tǒng)的初次訪問,,系統(tǒng)還沒生成session。但是訪問之后,,系統(tǒng)就會生成一個session,,而且,會在響應(yīng)流中設(shè)置響應(yīng)頭Set-Cookie,,其值為JESSIONID=xxx,。這樣瀏覽器對localhost:8080和cookie的聯(lián)系就有了記憶,瀏覽器會將其存儲起來,,可在調(diào)試工具中看到:

那么再次訪問http://localhost:8080/test1, 瀏覽器會主動在請求頭添加包括jsession的cookie信息

系統(tǒng)根據(jù)這個jsessionid找到session,,也就不會在響應(yīng)頭中添加Set-Cookie信息。

這里說一下cookie中的兩個重要屬性:

  • domain表示的是cookie所在的域,,默認為請求的地址,,如網(wǎng)址為www.test.com/test/test.aspx,那么domain默認為www.test.com,。而跨域訪問,,如域A為t1.test.com,域B為t2.test.com,,那么在域A生產(chǎn)一個令域A和域B都能訪問的cookie就要將該cookie的domain設(shè)置為.test.com,;如果要在域A生產(chǎn)一個令域A不能訪問而域B能訪問的cookie就要將該cookie的domain設(shè)置為t2.test.com。

  • path表示cookie所在的目錄,,默認為/,,就是根目錄。在同一個服務(wù)器上有目錄如下:/test/,/test/cd/,/test/dd/,,現(xiàn)設(shè)一個cookie1的path為/test/,,cookie2的path為/test/cd/,那么test下的所有頁面都可以訪問到cookie1,,而/test/和/test/dd/的子頁面不能訪問cookie2,。這是因為cookie能讓其path路徑下的頁面訪問。

疑點

下面,就該說下我的疑點了,。

情況1:

但是當我在8081的一個方法中,,重定向到8080的一個路徑時,發(fā)現(xiàn)了奇怪的現(xiàn)象,。

8081系統(tǒng)的方法如下:

   @GetMapping('/test')
    public void get1(HttpServletRequest request, HttpServletResponse response) throws IOException {
        HttpSession session = request.getSession();
        String id = session.getId();
        System.out.println(id);
        response.sendRedirect('http://localhost:8080/test1');
    }

8080系統(tǒng)的被重定向路徑如下:

    @GetMapping('/test1')
    public void get11(HttpServletRequest request, HttpServletResponse response) throws IOException {
        HttpSession session = request.getSession();
        String id = session.getId();
        System.out.println(id);
    }

1,、

初次訪問localhost:8081/test 得到兩次請求的信息,一次是重定向的,,一次是8080的

這說明對8081系統(tǒng)的初次訪問,,是沒有發(fā)送jsessionid信息的,而8081系統(tǒng)生成了一個id為CAAB6AED34716A0394705BDE8CAC0042的session并設(shè)置到了響應(yīng)頭,,再次訪問8081時理應(yīng)會帶上這么一個id,。

2、

這個對8080系統(tǒng)的請求中帶有jsessionid為CAAB6AED34716A0394705BDE8CAC0042的cookie信息,,要知道,,我們對8080的訪問也是初次的,那么為什么會帶上jsessionid呢,?而且這個jsessionid明顯是在8081系統(tǒng)中生成并設(shè)置到響應(yīng)頭的的jsessionid,。這個現(xiàn)象我用谷歌和edge瀏覽器分別嘗試過,都是這樣,。那么是不是說明,,瀏覽器把這個重定向到localhost:8080的請求當成是同域的請求了 。

暫且放下這個疑惑,,繼續(xù)往下驗證,。由于這個請求是對8080的系統(tǒng)的訪問,由于是初次訪問,,系統(tǒng)根本沒有id為CAAB6AED34716A0394705BDE8CAC0042的session,,因此只好生成一個新的session,在響應(yīng)頭中增加Set-Cookie,。

3,、
再次訪問localhost:8081/test,這時根據(jù)上文說的,,“再次訪問8081時理應(yīng)會帶上這么一個id”,,也就是在cookie中帶上JSESSION=CAAB6AED34716A0394705BDE8CAC0042, 但是,我發(fā)現(xiàn)它帶的卻是在系統(tǒng)8080中生成的BA0D2C939ADEC087C0A5F0C9B3354891 !??!

這就導致了8081找不到session又再次生成了一個新的session,循環(huán)往復,,每次對8081的訪問都會產(chǎn)生新的session,。而這情況,,我覺得很明顯,是瀏覽器把對8081的訪問當成是于8080同源的了,。

基于此推論,,我模擬了另一種實驗情況,,去掉重定向的功能:

情況2:

在本地開兩個web服務(wù),,端口分別是8080,8081。

localhost:8081/test

    @GetMapping('/test')
    public void get1(HttpServletRequest request, HttpServletResponse response) throws IOException {
        HttpSession session = request.getSession();
        String id = session.getId();
        System.out.println(id);

    }

localhost:8080/test1

    @GetMapping('/test1')
    public void get11(HttpServletRequest request, HttpServletResponse response) throws IOException {
        HttpSession session = request.getSession();
        String id = session.getId();
        System.out.println(id);
    }

1,、第一次訪問8081/test

沒有cookie,,服務(wù)器設(shè)置set-cookie,正常,。

2,、第二次訪問8081/test

cookie與上次的set-cookie一致,正常,。

3,、第一次訪問8080/test1


瀏覽器把8081/test的cookie發(fā)過去了。8080的服務(wù)器找不到這個jsessionid,,又重新設(shè)置了jsessionid,,等到再次訪問8081/test時,大家也能猜到會發(fā)生什么了吧,。

推論

至此,,我斗膽推論,瀏覽器會對同一ip不同端口的服務(wù)訪問認定是可以進行cookie共享的,,兩個cookie的domain是一致的,。而這種cookie的截圖也一定程度上印證了我的想法:

cookie的domain似乎只認定域名,無關(guān)端口,。

但是根據(jù)瀏覽器的同源策略,,同域名不同端口的訪問也應(yīng)該是跨域的啊。除非瀏覽器的域跟cookie的domain在概念上是有區(qū)別的,,對于這點,,我沒找到確切的官方資料,但網(wǎng)上大神是這么說的:

解決方案

基于上面的未查閱官方資料而做出的不嚴謹?shù)耐普?,我想,,只要完全避免同域的情況就可以避開這個問題。于是我把8081和8080系統(tǒng)分別部署在兩個機器上,。由于不同ip,,這樣無論如何,兩個cookie都不會是同domain的了,。果然,,結(jié)果是沒有問題的,。

不足

雖然這個解決方案避開了同域的問題,但是沒有徹底解決,,畢竟同域的系統(tǒng)相互之間的訪問也是有必要的,,為此希望能獲得更多的建議或者資料,補充這方面知識的不足,,讓我徹底解決這個問題,。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多