iT邦幫忙

2021 iThome 鐵人賽

DAY 7
0
永豐金融APIs

30天全端挑戰!React+Spring Boot+Mongo DB 串接永豐API 打造金融網站系列 第 7

[Day 07] - Spring Boot 實作登入驗證(一)(TOKEN or SESSION?)

昨天在controller有做了一個post的登入api,
不過也就只是驗證你傳入的帳密有沒有正確而已,要怎麼實際應用在網頁的登入驗證上呢?

Session 驗證

一般在jsp網站的做法應該是驗證客戶的帳密是否正確,
正確就在客戶的session加一個已登入的attribute
然後還有寫一個filter,在需要登入的頁面驗證這位客戶的session有沒有登入,差不多就這樣!

寫起來也很簡單,因為Servlet會幫我們把session的ID,一般預設叫是JSESSIONID
存放到client的cookie裡面,我們不用再在程式裡多寫什麼複雜的操作,

以某銀行為例,我們在cookie裡可以看到JSESSIONID
https://ithelp.ithome.com.tw/upload/images/20210921/20128973GBYcwEQroJ.png

可以看到我們的cookie裡存了一個叫JSESSIONID的值,就是Server發配給我的session id
一般是這樣,當我們輸入帳密登入時,
Server端驗證帳密無誤,會拿你帶著的session id,
找出你的session(存放在Server裡面),然後加入一些身分判斷的attriubte,

我們每次發送request時都會一併帶上session id,
透過fillter的實作
Server端會拿我們帶的session id來從Server本身儲存的眾多session中,找出這個特定session
看看這個客戶的session有沒有已登入的資訊,有的話就確認身分了,

這樣的意思即是,如果有一萬個客戶在線上,那Server就要儲存10,000個不同人的session,
除了對Server造成負擔外,如果是有多台主機,還要處理主機間session要怎麼共享的問題

所幸現在普遍用redis就能解決以上兩個問題

那還有另一個問題是,如果我盜用這個人的session id,不就等於取得這個人的登入身份了嗎

理論上來講,是的

可以看看幾個月前的新聞

駭客解釋,首先他們先在網路花 10 美元買被盜用的 Cookie,因 Cookies 保存特定使用者的登錄資訊,讓駭客可冒充他人身分登入。駭客利用被盜的 Cookie,獲得 EA 使用的 Slack 頻道許可權,並進入 EA 的 Slack。

雖然新聞中只說Cookie,其實道理差不多,總之就是Cookie裡面用來確認身分的東西被人盜用了
不過一般銀行會在網站加上Security Header保護Cookie的安全(Set-Cookie: ....; Secure; HttpOnly),
讓Cookie不會這麼容易被盜走,且本身交易流程也有驗證的機制
所以其實也不用太擔心

JWT TOKEN 驗證

我查了網路上大部分Spring Boot前後端分離的作法,很流行用jwt這種以token取代session的做法,
jwt是一串由Server端加密後發配給client的token,
client收到token之後,在需要的情況下,發request就帶著這個token,讓Server解密並驗明身分,

這邊要注意的是,因為token本身就保存了client的驗證資訊,
一般情況下,Server發配token後就不再保存token,
只需要在client丟request過來時解密client的token,看看是否正確就行了

舉個簡單例子,

有一天我被警察攔檢,
session就像是我(client)只報給警察(server)我的身分證字號: 我是誰?家裡住哪?你再自己用身分證字號去查
token就是我(client)直接身分證給警察(server): 警察只需要確認身分證是真,我是誰、住哪,也不用去查了(因為都寫在證上)

這麼做的優點是減少了Server端的負擔,且不必再操心session共享跟server負擔大的問題,
不過缺點是Server端無法控制token的失效,因為以token來講Server只做驗證的動作,
如果哪天因為某些原因,你要強制某個client登出,不好意思沒辦法,就只能等他的token過期或他自己登出,
而使用session的話就可以透過移除server上該客戶的session資訊來做到強制登出

雖然token另有搭配refresh token來達到Server控制的作法,不過這樣就有點失去JWT Stateless的初衷了...
說到底還是要看業務情境,而且一般應該也很少有要踢退客戶的情境,鎖ip還比較常見

前面講到,session因為session id存在cookie裡有被盜的風險,那token有嗎?
我在查資料的時候有看到文章寫說

JWT因為不是儲存在瀏覽器cookie,所以能避免CSRF(跨站請求偽造)的安全問題

想說有這麼神奇嗎?那token是儲存在哪?怎麼避免的?

查到的作法是存在html5的功能:local storage
不過只要東西存在客戶端就一樣有被盜用的風險,
甚至,用local storage還更容易被第三方取得...
此外cookie目前已經有很成熟的保護機制(前述的security header),
且token其實也可以存在cookie裡,端看實作的方式,所以實際上並沒有誰比較不安全的問題

因此安全性不能算是JWT的賣點

那麼,我要用哪種驗證方式?
因為我不是要做什麼百萬流量的網站、不會遇到session的資源問題,
選session的方式應該是最簡單的方法

但是這次參加鐵人賽就是要玩點不一樣的,明天就以jwt來實作!


上一篇
[Day 06] - 用Spring Boot 建立Controller
下一篇
[Day 08] - Spring Boot 實作登入驗證(二)(JWT淺析)
系列文
30天全端挑戰!React+Spring Boot+Mongo DB 串接永豐API 打造金融網站30

尚未有邦友留言

立即登入留言