天天看點

軟體測試丨接口測試面試題:Session、cookie、token有什麼差別?

作者:測試人666
公衆号搜尋:TestingStudio 霍格沃茲的幹貨都很硬核

HTTP是一個沒有狀态的協定,這種特點帶來的好處就是效率較高,但是缺點也非常明顯,這個協定本身是不支援網站的關聯的,比如https://ceshiren.com/和https://ceshiren.com/t/topic/9737/7這兩個網站,必須要使用别的方法将它們兩個關聯起來。那就是session 、cookie 、token。

  • session 即會話,是一種持久網絡協定,起到了在使用者端和伺服器端建立關聯,進而交換資料包的作用。
  • cookie 是“小型文本檔案”,是某些網站為了辨識使用者身份,進行 session 跟蹤而儲存在使用者本地終端上的資料(通常經過加密),由使用者用戶端計算機暫時或永久儲存的資訊。
  • token 在計算機身份認證中是令牌(臨時)的意思,在詞法分析中是标記的意思。一般作為邀請、登入系統使用。

示範環境搭建

與 get、post 差別實戰詳解 章節相同,為了避免其他因素的幹擾,使用 Flask 編寫一個簡單的 demo server(Flask 的安裝與啟動參考 get、post 差別實戰詳解 章節),來示範 cookie 與 session。

demo server 示範代碼

from flask import Flask,session,Request, request,make_responseapp = Flask(__name__)request: Requestapp.secret_key = "key"@app.route('/')def hello_world():
    return 'Hello, World!'@app.route("/session")def session_handle():
    #讀取請求
    for k, v in request.args.items():
    #收到請求後寫入session
        session[k] = v
    #建立伺服器響應,将session的内容列印出來
    resp = make_response({k: v for k, v in session.items()})
    for k, v in request.args.items():
    #給伺服器設定cookie,并添加cookie字元串進行辨別
        resp.set_cookie(f"cookie_{k}", v)
    return resp           

分析 session、cookie、token

session、cookie 差別示範

首先使用浏覽器的無痕模式對示範網站發起通路,并傳入 a、b 兩個參數 以一次請求為例,檢視 cookie 的傳遞過程

第一次請求的請求頭資訊如下,可以看到沒有任何的 cookie 資訊:

GET /session?a=1&b=2 HTTP/1.1
Host: 127.0.0.1:5000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en           

第一次請求的響應頭資訊,對用戶端傳回了 set-cookie 字段:

HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 18Set-Cookie: cookie_a=1; Path=/
Set-Cookie: cookie_b=2; Path=/
Vary: Cookie
Set-Cookie: session=eyJhIjoiMSIsImIiOiIyIn0.YKSvNA.2sSLXbraXxQ-MfKOLhoLJPZmV9U; HttpOnly; Path=/
Server: Werkzeug/1.0.1 Python/3.8.7
Date: Wed, 19 May 2021 06:24:52 GMT           

第二次請求的請求頭資訊,用戶端向服務端請求時請求頭多出了一個 cookie 資訊,并送出了和第二次 set-cookie 相同的資訊:

GET /session?a=1&b=2 HTTP/1.1
Host: 127.0.0.1:5000
...省略...
Cookie: cookie_a=1; cookie_b=2; session=eyJhIjoiMSIsImIiOiIyIn0.YKSvNA.2sSLXbraXxQ-MfKOLhoLJPZmV9U           

當使用者通路帶 cookie 浏覽器時,這個伺服器就為這個使用者産生了唯一的 cookie,并以此作為索引在伺服器的後端資料庫産生一個項目,接着就給用戶端的響應封包中添加一個叫做 Set-cookie 的首部行,格式為 k:v。

這樣當該使用者下次再通路此網站時,就會在對伺服器發起請求的時候添加一個名 Cookie 的首部行。浏覽器由此就可以得知使用者的身份,進而使用者就不需要再次重新輸入一些個人資訊。

使用 curl 指令對網站發起了一個 get 請求,并傳入 a、b 兩個參數

curl 'http://127.0.0.1:5000/session?a=1&b=2' -v -s &>session           

檢視 session 檔案内的請求以及響應内容

*   Trying 127.0.0.1...
* TCP_NODELAY set* Connected to 127.0.0.1 (127.0.0.1) port 5000 (#0)> GET /session?a=1&b=2 HTTP/1.1
> Host: 127.0.0.1:5000
> User-Agent: curl/7.64.1
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: application/json
< Content-Length: 18< Set-Cookie: cookie_a=1; Path=/
< Set-Cookie: cookie_b=2; Path=/
< Vary: Cookie
< Set-Cookie: session=eyJhIjoiMSIsImIiOiIyIn0.EWX6Qg.M8tEGPyRhlf0iUiLktEqup-4e-U; HttpOnly; Path=/
< Server: Werkzeug/1.0.1 Python/3.7.5
<{ [18 bytes data]* Closing connection 0{"a":"1","b":"2"}           

從上面可以發現,與上一章節内容不同的是響應值多出了 3 個Set-Cookie字段。下面有一個Set-Cookie顯示為session=eyJhIjoiMSIsImIiOiIyIn0.EWX6Qg.M8tEGPyRhlf0iUiLktEqup-4e-U; HttpOnly; Path=/,由此可見 session 一般是加密串格式,可以通過 cookie 傳遞。

token 示範

token 的使用有一個非常經典的場景,就是在 github 中的使用。在 github->settings->Developer settings->Personal access tokens 中,可以生成一個 token 用于通路 github 的 api,這個 token 是沒有時效性的,“任何人”可以使用它們代替通過 HTTPS 的 Git 密碼,也可以用來通過基本身份驗證向 API 進行身份驗證。

軟體測試丨接口測試面試題:Session、cookie、token有什麼差別?

使用 OAuth 令牌對 GitHub API 進行身份驗證(因傳回結果個人資訊太多是以省略展示)

$ curl -u username:$token https://api.github.com/user           

token是無狀态的,用戶端傳遞使用者資料給服務端後,服務端将資料加密就生成了token并傳回給用戶端。這樣用戶端每次通路時都傳遞token,而服務端解密token之後,即可了解客戶的資訊。

在 github 中,token 隻會生成一次,且不會過期,不過在很多其他的 web 應用網站,token 會存在過期機制。

session、cookie、token 的差別

@startuml
autonumber
title session、cookie過程
participant 用戶端 as c
participant 伺服器 as s

c -> s: 第一次請求
s -> s: 建立SessionID并儲存
s -> c: 傳回SessionID,并Set-Cookie
c -> c: Cookie儲存\n在浏覽器
c -> s: 第二次請求,請求中攜帶Cookie和SessionId
s -> s: 判斷SessionId\n屬于哪個使用者
s -> c: 響應 

@enduml           
@startuml
autonumber
title token身份驗證流程

participant 用戶端 as c
participant 伺服器 as s

c -> s: 第一次請求,攜帶使用者資訊(賬戶、密碼)
s -> s: 使用者資訊加密\n之後得到token
s -> c: 傳回token
c -> s: 請求時攜帶token
s -> s: 對token解密之後做認證
s -> c: 響應 

@enduml           
  • session 存儲在伺服器端,cookie 存儲在用戶端。
  • cookie 可設定為長時間保持,session 一般失效時間較短,用戶端關閉(預設情況下)或者 session 逾時都會失效。
  • session記錄會話資訊,token不會記錄會話資訊。token是無狀态的。