欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java開發(fā)web前端cookie session及token會話機制詳解

 更新時間:2021年10月21日 17:07:06   作者:>no problem<  
如果把人體比作一個web系統(tǒng)的話,cookie、session和token就好像人體的經(jīng)絡(luò)和血管一樣,而web系統(tǒng)中的數(shù)據(jù),就好像人體的血液一樣。血液依靠著血管在人體內(nèi)流動,就如數(shù)據(jù)根據(jù)cookie和session機制在web系統(tǒng)中流動一樣

而web系統(tǒng)開發(fā)者就好比一個醫(yī)術(shù)精湛的醫(yī)生,醫(yī)生需要十分清楚人體的經(jīng)絡(luò)和血液流向才能對癥下藥,而web系統(tǒng)開發(fā)者需要十分清楚cookie、session機制,才能迅速解決疑難BUG,開發(fā)出更好的web系統(tǒng)?!f

引入:

我們都知道http協(xié)議本身是一種無狀態(tài)的協(xié)議,一個普通的請求大致分為三步:

1、客戶端發(fā)送請求給服務(wù)器

2、服務(wù)器處理該請求

3、服務(wù)器將處理結(jié)果響應(yīng)該客戶端。

之后該客戶端再次向該服務(wù)區(qū)發(fā)送請求后,服務(wù)器端并不能知道這兩個請求是否是同一個瀏覽器或用戶發(fā)出來的。所以作為web服務(wù)器必須能夠采用某種方式來唯一識別同一個用戶,并記錄該用戶的狀態(tài)。而這同一個客戶端與服務(wù)器端的在一段時間內(nèi)的多次交互,我們就可以稱該客戶端為該服務(wù)器端的一個客戶端會話窗口,有了會話窗口,我們就能確定哪個請求是哪個用戶發(fā)出的了,從而可以實現(xiàn)會話跟蹤,并記錄用戶的行為。

概念:

會話:可以理解為用戶打開瀏覽器,訪問該web服務(wù)器的多個資源,然后關(guān)閉瀏覽器,這中間的一系列過程稱之為一個會話。

有狀態(tài)的會話:瀏覽器發(fā)送的每一次請求,每一個會話都要有唯一的標識來唯一標識自己,當瀏覽器發(fā)送請求的時候就帶上這個標識來讓服務(wù)器識別,從而實現(xiàn)有“狀態(tài)”的會話。

javaweb中有兩種實現(xiàn)會話的機制:

1)Cookie機制

2)Session機制

PS:cookie和session是瀏覽器與服務(wù)器交互的一種規(guī)范,有專門的的組織對該規(guī)范進行定義,只要瀏覽器或服務(wù)器遵守了該規(guī)范,我們就能使用cookie和session。其他能做web開發(fā)的高級語言也有,只是實現(xiàn)方式不同罷了。

一、cookie機制

1、基本介紹

1)cookie機制采用的是在客戶端保持 HTTP 狀態(tài)信息的方案。當瀏覽器訪問WEB服務(wù)器的某個資源時,WEB服務(wù)器會在HTTP響應(yīng)頭中添加一個鍵值對傳送給瀏覽器,再由瀏覽器將該cookie放到客戶端磁盤的一個文件中,該文件可理解為cookie域(鍵值對的集合),往后每次訪問某個網(wǎng)站時,都會在請求頭中帶著這個網(wǎng)站的所有cookie值。(至于怎么區(qū)分不同網(wǎng)站的cookie的,很簡單,每個網(wǎng)站都給他一個唯一標識比如網(wǎng)址等,每次打開某網(wǎng)址時,就查詢該網(wǎng)站下的所有cookie值即可。)

2)每一個cookie都有一個name和一個value,且name是唯一的。相同名字時,后者會覆蓋掉前者(類似哈希表的key的效果)。

3)一個WEB瀏覽器也可以存儲多個WEB站點提供的Cookie。瀏覽器一般只允許存放300個Cookie,每個站點最多存放20個Cookie,每個Cookie的大小限制為4KB。

2、分類

1)會話級別的cookie

默認情況下它是一個會話級別的cookie,存儲在瀏覽器的內(nèi)存中,用戶退出瀏覽器之后被刪除。

2)持久化的cookie

若希望瀏覽器將該cookie存儲在磁盤上,則需要設(shè)置該cookie的生命周期setMaxAge,并給出一個以秒為單位的時間。將最大時效設(shè)為0則是命令瀏覽器刪除該cookie。

3、cookie的作用域

cookie的domain和path屬性定義了cookie的作用范圍,即訪問哪些網(wǎng)站或url時,會自動的帶著該cookie。domain即域名,默認是當前主機(不包括子域名),path默認是*(所有路徑),即域名后面的的路徑。大部分情況下我們都是使用默認的設(shè)置即可。

4、基本原理

當一個瀏覽器訪問某web服務(wù)器時,web服務(wù)器會調(diào)用HttpServletResponse的addCookie()方法,在響應(yīng)頭中添加一個名叫Set-Cookie的響應(yīng)字段用于將Cookie返回給瀏覽器,當瀏覽器第二次訪問該web服務(wù)器時會自動的將該cookie回傳給服務(wù)器,來實現(xiàn)用戶狀態(tài)跟蹤。

5、常用API

javax.servlet.http.Cookie類來封裝Cookie信息,它包含有生成Cookie信息和提取Cookie信息的各個屬性的方法。

1)public Cookie(String name,String value)

2)setMaxAge(int longTime)與getMaxAge方法:設(shè)置和獲取cookie的最大有效時長。setMaxAge(0) 表示刪除磁盤上的某個cookie。

注意:

cookie沒有提供修改方法,當name一樣時,覆蓋原來的就算是更新了。

刪除也是,setMaxAge(0),當name一樣時,原來的會被覆蓋掉,新建的沒有生命周期,也會被立馬刪除。

3)setPath與getPath方法 :設(shè)置或讀取Cookie的作用范圍。

4)HttpServletResponse接口中定義了一個addCookie(Cookie cookie)方法,它用于在發(fā)送給瀏覽器的HTTP響應(yīng)消息中增加一個Set-Cookie響應(yīng)頭字段。

5)HttpServletRequest接口中定義了一個getCookies方法,它用于從HTTP請求消息的Cookie請求頭字段中讀取所有的Cookie項。

6)getName方法 :獲取到cookie的name。

7)setValue(String value)與getValue方法:設(shè)置和獲取cookie的value。

6、基本應(yīng)用

自動登錄、跟蹤用戶上次訪問站點的時間、顯示最近瀏覽信息等。

這是我之前寫的一個使用cookie進行自動登錄的服務(wù)器代碼,很早了都。

     //如果cookie中有customer信息,就放到session中
     boolean checkCustomerCookie(HttpServletRequest request) throws UnsupportedEncodingException {
        Cookie[] cookies = request.getCookies();
         if (cookies != null) {
            for (Cookie cookie : cookies) {
                String cookieName = cookie.getName();
                //如果有,解密后拿cookie中的值和數(shù)據(jù)庫中的值進行比較
                if (Constant.cookieCustomerKey.getName().equals(cookieName)){
                    String cookieValue = cookie.getValue();
                    String decry = EncrypUtils.Base64Util.decry(cookieValue);
                    Customer customer1 = JsonUtils.stringToObject(decry, Customer.class);
                    Customer customer2 = customerService.checkLogin(customer1.getPhoneNumber(), customer1.getPassword());
                    if (customer2 != null){
                        //放入到session中,放行
                        request.getSession().setAttribute("customer",customer2);
                        //自動登錄時,更新用戶的在線狀態(tài)
                        Customer onlineCustomer = new Customer();
                        onlineCustomer.setId(customer2.getId());
                        onlineCustomer.setOnlineStatus(String.valueOf(Constant.ONLINESTATUS.getCode()));
                        customerService.updateById(onlineCustomer);
                        return true;
                    }
                }
            }
         }
        return false;
    }

7、Cookie中存儲中文問題

cookie中存儲中文會出現(xiàn)中文亂碼,需要對value進行額外的編碼

1、base64編碼

存儲:Base64.getEncoder().encodeToString(content.getBytes("utf-8"));

讀?。簄ew String(Base64.getDecoder().decode(cookie.getValue()),"utf-8")

2、URLEncoder類

存儲:Cookie cookie = new Cookie("userName", URLEncoder.encode("你好世界", "UTF-8"));

讀?。篣RLDecoder.decode(cookie.getValue(), "UTF-8")

二、session機制

1、基本介紹

session機制采用的是在服務(wù)器端保持 HTTP 狀態(tài)信息的方案。為了加速session的讀取和存儲,web服務(wù)器中會開辟一塊內(nèi)存用來保存服務(wù)器端所有的session,每個session都會有一個唯一標識sessionid,根據(jù)客戶端傳過來的jsessionid(cookie中),找到對應(yīng)的服務(wù)器端的session。為了防止服務(wù)器端的session過多導致內(nèi)存溢出,web服務(wù)器默認會給每個session設(shè)置一個有效期, (30分鐘)若有效期內(nèi)客戶端沒有訪問過該session,服務(wù)器就認為該客戶端已離線并刪除該session。

保存sessionID的方式

1)cookie中

通過一個特殊的cookie,name為JSESSIONID,value為服務(wù)器端某個 session的ID,默認的方式。但是當瀏覽器禁用cookie后session就會失效。

2)url重寫

當瀏覽器Cookie被禁時用。

就是把session的id附加在URL路徑的后面。附加的方式也有兩種,一種是作為URL路徑的附加信息,另一種是作為查詢字符串附加在URL后面。

做法:

1、response.encodeURL(String url)用于對表單action和超鏈接的url地址進行重寫

2、response.encodeRedirectURL(String url) 用于對sendRedirect方法后的url地址進行重寫。

這兩個方法很智能,若瀏覽器禁用了cookie,就默認會進行url重寫(url中帶上sessionid),當用戶瀏覽器沒有禁用cookie時,就不在URL后附加sessionid。

用法就是代替response.sendRedirect(String url)。、

2、基本原理

當用戶發(fā)送一個請求到服務(wù)器端時,服務(wù)器會先檢查請求中是否含有sessionid(存在cookie中或者在url中),

》》如果不存在sessionid(說明是第一次請求),就會為該請求用戶創(chuàng)建一個session對象,并將該session對象的sessionid(放到響應(yīng)頭的set-cookie中,格式set-cookie:sessionid,下次再請求時cookie中就會有一個name為jsessionid的cookie,value就是sessionid)響應(yīng)給客戶端。

》》如果存在sessionid,就會在服務(wù)器端查找是否有該sessionid對應(yīng)的session,如果有就使用,沒有就創(chuàng)建一個。

所以說,服務(wù)器端的session和客戶端的cookie是息息相關(guān)的,若是沒有了cookie,又不做其他處理的話,服務(wù)器端的session也沒了。

3、常用API

getId()方法:得到sessionid。

invalidate()方法:讓session立刻失效。

getAttribute(String key):根據(jù)key獲取該session中的value。

setAttribute(String key,Object value):往session中存放key-value。

removeAttribute(Stringkey):根據(jù)key刪除session中的key-value。

getServletContext():得到ServletContext。

setMaxInactiveInterval(long timeout)/getMaxInactiveInterval:設(shè)置/獲取session的最大有效時間。

getCreationTime方法:獲取session的創(chuàng)建的時間。

getLastAccessedTime方法:獲取session最后一次訪問的時間。

getSession():從HttpServletRequest中獲取session。

4、基本應(yīng)用 跨瀏覽器的會話跟蹤

因為cookie在多個瀏覽器之間是共享的(但是不能跨域),所以可以將sessionid存在cookie中,再把cookie存入磁盤中,然后在其他瀏覽器中再次訪問該服務(wù)器時,就會讀取到cookie中的sessionid,從而回到上次訪問的頁面了。

一段示例代碼:

session.setMaxInactiveInterval(2*3600);//session 保存?zhèn)z小時
Cookie cookie=new Cookie("JSESSIONID",session.getId());//sessionid放到cookie中
cookie.setMaxAge(2*3600);//客戶端的cookie也保存?zhèn)z小時 
cookie.setPath("/");//cookie作用范圍設(shè)為整個項目
response.addCookie(cookie);//給瀏覽器返回該Cookie

5、常見問題

1、關(guān)閉瀏覽器后cookie會消失嗎?

答:看情況。

經(jīng)過上面關(guān)于cookie的分析之后我們知道,cookie默認是存在于瀏覽器內(nèi)存中的,若此時cookie沒有持久化,瀏覽關(guān)閉后cookie會消失;若此時cookie進行了持久化,瀏覽器關(guān)閉后cookie不會消失。

2、關(guān)閉瀏覽器后session會消失嗎?

答:看起來會實際上不會。

這個問題需要從以下兩個方面考慮:

1)從服務(wù)器端考慮

我們知道session是存在于服務(wù)器端內(nèi)存中的,和瀏覽器沒有關(guān)系,所以瀏覽器關(guān)閉后,服務(wù)器端的session不會消失。(除非服務(wù)器重啟或session達到了過期時間)

2)從瀏覽器端考慮

我們知道瀏覽器是根據(jù)cookie中的jesessionid值來唯一找到服務(wù)器端的session的,此時若cookie沒有持久化,瀏覽器關(guān)閉后cookie也跟著消失。所以當用戶再次打開瀏覽器后,由于沒有了cookie中的jesessionid,自然也無法唯一找到服務(wù)器端的session,對用戶來說,確實是瀏覽器關(guān)閉后再次打開就無法找到上次的會話了,誤以為是關(guān)閉瀏覽器后服務(wù)器端的session也跟著消失,其實還在。

三、token

1、token是啥?

token,可以翻譯成"令牌",本質(zhì)上它是一個全局唯一的字符串,用來唯一識別一個客戶端。但它不像cookie和session一樣是一種web規(guī)范,個人認為他是借鑒了cookie和session工作的原理,進而延伸出來的一種維持用戶會話狀態(tài)的機制。

2、token解決了什么問題?

token解決了session依賴于單個Web服務(wù)器的問題。單體應(yīng)用時用戶的會話信息保存在session中,session存在于服務(wù)器端的內(nèi)存中,由于前前后后用戶只針對一個web服務(wù)器,所以沒啥問題。但是一到了web服務(wù)器集群的環(huán)境下(我們一般都是用Nginx做負載均衡,若是使用了輪詢等這種請求分配策略),就會導致用戶小a在A服務(wù)器登錄了,session存在于A服務(wù)器中,但是第二次請求被分配到了B服務(wù)器,由于B服務(wù)器中沒有用戶小a的session會話,導致用戶小a還要再登陸一次,以此類推。這樣用戶體驗很不好。當然解決辦法也有很多種,比如同一個用戶分配到同一個服務(wù)處理、使用cookie保持用戶會話信息等。

我們今天討論的是用戶會話信息集中存儲的這種方案。類比之前cookie和session的機制,在請求中根據(jù)cookie中的jesessionid來自動找到服務(wù)器端的session,從而從session中取出當前用戶的會話信息。

Session session = request.getSession();// 獲取session
session.getAttribute("user") // 獲取session中的用戶信息

3、我們可以模擬cookie和session的這種機制:

①、cookie中是根據(jù)jesessionid來找到服務(wù)器端的session的,jesessionid就是一個全局唯一的隨機字符串,我們也可以生成一個全局唯一的字符串比如使用UUID或時間戳加隨機字符串的形式;

②、web服務(wù)器在內(nèi)存中存儲所有的session,每個session都有一個唯一的id標識,value就是session本身,session里面又有好多鍵值對。數(shù)據(jù)在內(nèi)存中、key-value形式的、value里面又有好多鍵值對,這簡直就是對redis的哈希表十分準確的描述啊,所以我們可以使用redis的哈希類型來模型服務(wù)器端的session。

③、有了客戶端的隨機字符串,有了服務(wù)器端的會話信息存儲,接下來就讓他們匹配起來就完事了,next:

cookie和session機制中是根據(jù)cookie中的jesessionid來自動找到服務(wù)器端的session,說是自動查找,其實是我們調(diào)用了他封裝好的方法request.getSession()獲取的,這個request中就包含了本次請求的所有信息,而調(diào)用的getSession()方法中,肯定做了這件事——獲取請求頭中cookie的jesessionid的值,根據(jù)這個值到服務(wù)器的內(nèi)存中找到對應(yīng)的session并返回。所以我們也完全可以模仿它這種機制:我們可以在用戶第一次請求該web服務(wù)器時或是用戶登錄該web服務(wù)器時,生成一個全局唯一的token返回給前端存儲,同時將該用戶信息存到redis中并設(shè)置有效期,之后每次請求中都在請求頭中帶著這個token,服務(wù)器端根據(jù)這個token到redis中查找對應(yīng)的用戶信息,即得到了我們所說的 "session"。

客戶端的token我們可以這樣傳:

  $.ajax({
           headers:{"token":localStorage.getItem('token')},
           type: 'get',
           url:'/xxx/xxx/xxx',
           dataType: 'json',
           success: function(we) {
                // some code
             });
           },

服務(wù)器端的用戶信息我們可以這樣獲取:

 /**
  * 返回當前用戶
  * @return
  */
public User getCurrUser(){
    ServletRequestAttributes servletRequestAttributes = 
    (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
    String token = servletRequestAttributes.getRequest().getHeader("token");
    String strUser = RedisUtils.get(token);
   return JsonUtils.stringToObject(strUser,User.class);
}

ok,關(guān)于cookie、session和token暫時就這么多,能看到這兒也不容易,點個贊或評論一下再走,順便給自己也加點經(jīng)驗值。 這種雙贏的事情以后要多做啊~希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論