Spring Security 認證原理

    1. 背景介紹: 在認識Spring Security以前,全部的權限驗證邏輯都混雜在業務邏輯中,用戶的每一個操做之前可能都須要對用戶是否有進行該項操做的權限進行判斷,來達到認證受權的目的。相似這樣的權限驗證邏輯代碼被分散在系統的許多地方,難以維護。 spring security的簡單原理: ![輸入圖片說明] 其實spring security這樣的權限框架就是根據一系列的依賴代理(delegates)和servlet過濾器來實現的。 Spring security使用衆多的攔截器對url攔截,以此來管理權限。大體流程: 輸入圖片說明
    1. 這裏是列表文本這裏是列表文本認證過程—Authentication具體實現類的對象—>:SecurityContextHolder 輸入圖片說明
    1. AuthenticationManager —>ProviderManager AuthenticationManager是一個用來處理認證(Authentication)請求的接口。在Spring Security中,AuthenticationManager的默認實現是ProviderManager。 輸入圖片說明 輸入圖片說明
    1. 校驗認證獲取用戶信息—>DaoAuthenticationProvider—>UserDetailsService接口:
  • 用戶信息—>數據庫: 輸入圖片說明輸入圖片說明 根據請求的用戶名加載對應的UserDetails,而後比對UserDetails的密碼與認證請求的密碼是否一致,一致則表示認證經過。Spring Security內部的DaoAuthenticationProvider就是使用的這種方式。其內部使用UserDetailsService來負責加載UserDetails,在認證成功之後會使用加載的UserDetails來封裝要返回的Authentication對象,加載的UserDetails對象是包含用戶權限等信息的。認證成功返回的Authentication對象將會保存在當前的SecurityContext中。經過Authentication.getPrincipal()返回一個UserDetails的實例。Spring Security內部使用的UserDetails實現類大都是內置的User類。 能夠自定義UserDetails,在該實現類中咱們能夠定義一些獲取用戶其它信息的方法,這樣就能夠直接從當前SecurityContext的Authentication的principal中獲取自定義的信息了。
    1. 這裏是列表文本SecurityContextHolder:用來保存SecurityContext 輸入圖片說明 **Q:**既然SecurityContext 是存放在 ThreadLocal 中的,並且在每次權限鑑定的時候都是從 ThreadLocal 中獲取 SecurityContext 中對應的 Authentication 所擁有的權限,而且不一樣的 request 是不一樣的線程,爲何每次均可以從 ThreadLocal 中獲取到當前用戶對應的 SecurityContext 呢? R: SecurityContextPersistentFilter: 輸入圖片說明 輸入圖片說明 在 Web 應用中這是經過 SecurityContextPersistentFilter 實現的,默認狀況下其會在每次請求開始的時候從 session 中獲取 SecurityContext,而後把它設置給 SecurityContextHolder,在請求結束後又會將 SecurityContextHolder 所持有的 SecurityContext 保存在 session 中,而且清除 SecurityContextHolder 所持有的 SecurityContext。這樣當咱們第一次訪問系統的時候,SecurityContextHolder 所持有的 SecurityContext 確定是空的,待咱們登陸成功後,SecurityContextHolder 所持有的 SecurityContext 就不是空的了,且包含有認證成功的 Authentication 對象,待請求結束後咱們就會將 SecurityContext 存在 session 中,等到下次請求的時候就能夠從 session 中獲取到該 SecurityContext 並把它賦予給 SecurityContextHolder 了,因爲 SecurityContextHolder 已經持有認證過的 Authentication 對象了,因此下次訪問的時候也就再也不須要進行登陸認證了。
    1. 這裏是列表文本AbstractSecurityInterceptor FilterSecurityInterceptor, MethodSecurityInterceptor, AspectJSecurityInterceptor(JoinPoint) 自定義:從數據庫中獲取用戶、權限、資源來實現權限管理 1) MySecurityFilter: 輸入圖片說明 從數據庫中獲取權限驗證的數據,因此要重寫FilterInvocationSecurityMetadataSource 接口, AccessDecisionManager 接口,UserDetailsService 接口。項目啓動後,進行資源請求時,就自動會去執行咱們重定義的類進行權限判斷。 a. MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource (資源數據定義) 加載全部url和權限的對應關係。 輸入圖片說明 b. MyAccessDecisionManager implements AccessDecisionManager 接口(過濾用戶請求) 輸入圖片說明 參數說明: 一、configAttributes 裝載了請求的url容許的角色數組 。這裏是從MySecurityMetadataSource裏的loadResourceDefine方法裏的atts對象取出的角色數據賦予給了configAttributes對象 二、authentication 裝載了從數據庫讀出來的角色數據。這裏是從MyUserDetailsService裏的loadUserByUsername方法裏的auths對象的值傳過來給 authentication 對象 [AbstractSecurityInterceptor有三個派生類 FilterSecurityInterceptor,負責處理FilterInvocation,實現對URL資源的攔截 MethodSecurityInterceptor,負責處理MethodInvocation,實現對方法調用的攔截 AspectJSecurityInterceptor,負責處理JoinPoint,主要是用於對切面方法(AOP)調用的攔截 還能夠直接使用註解對Action方法進行攔截,例如在方法上加 @PreAuthorize("hasRole('ROLE_SUPER')");負責權限的控制,若是請求的url在權限集合中有這個url對應的值,則放行。注:若是數據庫中沒有對這個url定義訪問的權限,默認是會被放行的] c. 認證管理器AuthenticationManager(用戶認證的入口)—>UserDetailsService接口、 ![輸入圖片說明] MyUserDetailServiceImpl:【登陸驗證+獲取用戶權限】 輸入圖片說明
相關文章
相關標籤/搜索