iT邦幫忙

2024 iThome 鐵人賽

DAY 21
0
佛心分享-SideProject30

從卡關到通關的Spring Boot 腦內風暴系列 第 21

一樣都能認證,我該選擇誰?-Token 與 Session

  • 分享至 

  • xImage
  •  

延續前一篇,同樣是與安全性有關的主題,這篇聚焦在認證跟授權,Spring Security提供安全管理功能,其中Token跟Session是最常見的驗證方式,但究竟有什麼不同呢?使用上又該如何選擇?

Session認證

Session主要是基於伺服器狀態的驗證方式,當使用者登錄時,伺服器會產生一個Session紀錄,此Session ID會存於瀏覽器Cookie中,並自動發送給伺服器,當客戶端發送請求時,都會將Session ID帶入,伺服器就會透過此Session ID來查找對應的使用者狀態。

Session的優點

  • 傳統Web適用。
  • 屬於Spring Security的預設,不用額外配置。
  • 前端處理較為簡單,不用手動操作Cookie,瀏覽器能自動處理。

Session的缺點

  • Session存於伺服器,因此,當規模變大時,伺服器負載會增加。
  • Sessionu依賴於伺服器的本地存儲,無法直接於多個伺服器共享,因此不適用於分佈式系統時。
    解決方式可使用Redise等方式來集中存儲Session。

Session使用範例

Spring Security預設會自動處理Session認證,因此配置以下基本設定即可:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurrity http) throws Exception {
        http   
            .authorizeRequests()  
                .anyRequest().authenticated() // 說明任何請求需經過認證
            .and()
            .formLogin()  // 啟用登入功能
                .permitAll()  // 允許所有使用者進入登入頁面
            .and()
            .logout()     // 啟用登出功能
                .permitAll(); // 允許所有使用者使用登出功能
    }
}

Token認證(JWT)

Token是屬於無狀態的認證方式,在使用者登錄後,伺服器會生成Token,並發送給客戶端,當客戶端每次請求時,都需要攜帶此Token,伺服器會用Token比對驗證來確認使用者身分,因此,不用將認證ID存於伺服器端。

Token的優點

  • Token特別適用於RESTful API,Token附加於每次請求的Header中,適用REST無狀態設計,符合現代開發趨勢。
  • Token狀態不用存於伺服器端,適合用於分佈式系統。
  • 可以跨平台於web、移動應用等各種API客戶端使用。

Token的缺點

  • Token發出後,無法立即註銷。此問題可透過黑名單機制解決,但要額外撰寫。
  • 承上述,若Token被竊取,過期前都是有效的,因此要額外設置安全機制,例如過期時間、敏感操作雙重認證。
  • 前端需手動儲存Token於LocalStorage或SessionStorage,發送API請求時,要將Token放入Authorization。

Token使用範例

Spring Boot當中,可使用JWT(JSON Web Token)實現Token認證:

@configuration
@EnableWebSecurity
public class SecurityConfig extends WebSeurityConigurerAdapter {
    @Override
    protect void configure(HttpSecurity http) throws Excepiton {
        http
            .csrf().disable()  // 關閉CSRF
            .authorizeRequests() 
                .antMatchers("/loggin").permitAll() // 放入免授權可拜訪的路徑
                .anyRequest.authenticated() // 其他需認證的路徑
            .and() (???)
            .addFilter(new JwtAuthenticationFiltr(authenticationManager())) // JWT過濾器
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 說明不用session
    }
}

綜合上述,Token使用越來越普遍,特別是現今追求為服務架構或跨多種設備的狀況下,Token更好適用這些場景,而Session則是簡單快速的選擇,特別適用於單一伺服器,用於傳統web場景。


上一篇
保護會員數據-Spring Boot的資料加密實踐
下一篇
錯誤也能優雅設計-選擇正確的 HTTP 狀態碼
系列文
從卡關到通關的Spring Boot 腦內風暴30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言