- session 授權認證原理
- 密碼儲存與加密
- jwt(JSON Web Token)驗證
- JWT 的無狀態認證機制
- 實踐與除錯
實現目標:在沒有判斷登入認證的情況下,訪問任意介面,直接跳轉到登入介面。
新增Spring Security
依賴來實現登入認證
session 授權認證原理
實現config.SecurityConfig
類
SessionID 相當於給瀏覽器頒發的一張臨時身份證,之後瀏覽器在執行業務操作的時候,都要隨身攜帶這個身份證。
1.sessionID 生成與儲存
login 頁面登入成功後,後端生成 SessionID,將其同時儲存在後端資料庫與瀏覽器的 Cookie 中
2.sessionID 和請求一起傳送給後端
每次向後端 Springboot 傳送請求的同時,會從 Cookie 中取出將 SessionID 一起傳送給後端 Springboot。Springboot 透過向資料庫查詢判斷當前 SessionID 是否存在以及是否過期
-
PS:後端查詢判斷
如果存在,將有關 SessionID 的資訊(包括對應的使用者名稱、過期時間)從資料庫中取出,判斷是否過期。
若 SessionID 過期或者根本不存在,則返回給使用者登入頁重新登入。
若 SessionID 沒有過期,則透過 SessionID 與使用者資訊 userInfo 的對映關係,將對應的 User 提取到上下文中(在 Contoller 中就可以透過一些 API 來拿到 User),成功進行授權頁面的訪問。 -
來源 https://gitee.com/XZHongAN
密碼儲存與加密
在config.SecurityConfig
類中,實現使用者密碼的加密儲存
放行登入、註冊等介面
如果直接用明文密碼來儲存,需要在資料庫中加上{noop}
標記,代表不需要加密直接判斷
-
BCrypt 是 一種用於密碼雜湊的安全演算法。藉助
BCryptPasswordEncoder
的encode()
方法更新資料庫中的明文密碼 -
要在新增階段就直接儲存加密階段的程式碼,用到 PasswordEncoder
jwt(JSON Web Token)驗證
對於前後端分離的情況,使用 session 可能會出現跨域問題。
瀏覽器的同源策略(Same-Origin Policy)限制了來自不同源(即不同的協議、域名或埠)互相之間的某些操作。
想象你住在一個嚴格管理的小區裡(瀏覽器),而小區有一條規定:你只能和住在同一棟樓裡的鄰居(同源伺服器)自由交流和分享東西(資料請求)。現在,你想要和住在隔壁樓的一個鄰居交換東西(跨域請求),但是物業(瀏覽器的同源策略)不允許你這麼做,除非隔壁樓的鄰居明確告訴物業,他們願意接受你,並且確認這次交換是安全的(CORS 策略)。如果你想透過物業的特殊通行證(Cookie)證明你的身份來進行這次交換,物業還需要驗證這個通行證是不是也被鄰居接受的(允許攜帶 Cookie 的跨域請求)。在使用 Session 認證時,如果沒有正確處理這些安全策略,你就無法成功地和不同樓棟的鄰居交換東西了。
比如 Ajax 請求資料。當你的前端應用嘗試從一個源向另一個源的伺服器傳送請求時,就會遇到跨域問題。
JWT 的無狀態認證機制
JWT 的 T 是指包含認證資訊的 Token。這個 Token 是在使用者成功登入後生成的,包含了一系列的宣告(Claims),例如使用者的 ID、Token 的發行者、過期時間等。
這個 Token 會被伺服器數字簽名後傳送給客戶端,客戶端隨後的每個請求都會攜帶這個 Token。
伺服器透過驗證這個 Token 的簽名來認證使用者的請求,而不需要儲存任何使用者狀態資訊。伺服器不需要儲存任何使用者狀態資訊,也就是“無狀態的認證機制”的“無狀態”。
jwt 驗證的優點
- 容易實現跨域
- 不需要在伺服器端儲存
- 對於有多個伺服器的情況,就可以實現用一個令牌來登入多個伺服器
新增依賴:
jjwt-api
jjwt-impl
jjwt-jackson
對於 url 可以分為兩大類:
- 公開可以訪問(本專案中,對於登入和註冊的 URL,公開可以訪問)
- 需要授權才能訪問
實踐與除錯
實現utils.JwtUtil
類,建立、解析 jwt token
實現config.filter.JwtAuthenticationTokenFilter
類,用來驗證 jwt token 是否合法有效,如果驗證成功,則將 User 資訊注入上下文中
配置config.SecurityConfig
類,放行登入、註冊等介面
登入一般是 post 請求。
登入如果是 get 請求,會將使用者名稱和密碼引數放在 url 連結中,明文傳輸。顯然不能這樣。
選擇 Post 請求,就沒法從瀏覽器輸入 URL 的方式進行訪問,不能在瀏覽器中除錯。有 2 種除錯方式
- 前端 ajax 除錯
- 用 postman(以後學習)
對於返回的 token
比如:
"eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI5OWE5ZThjZDNlZDI0OTI3YTZiMWMzNDk5MDU1ZDljMyIsInN1YiI6IjEiLCJpc3MiOiJzZyIsImlhdCI6MTY1ODk3MjYzMCwiZXhwIjoxNjYwMTgyMjMwfQ.iioSQLuAyzpYLPzTgGuhs1ODb6mYIzpqnz6K8VQqbWc"
在https://jwt.io/進行解析,可以得到對應的 userID。