SpringSecurity、Shiro、Oauth2.0、Cas


任何的流程必須通過語言能夠描述,才達到最終效果

認證和授權總流程

在這裏插入圖片描述
AnonymousAuthenticationFilter在所有認證過濾器最後,判斷SpringSecurityConetxt中是否存在Authentication,若不存在則設置一個AnonymousAuthentication。

認證技術技術選型

企業中大多使用Shiro框架和Spring Security進行用戶身份認證,而實現SSO的技術選型又有Spring Security Oauth2.0和CAS,它們都可以很好的實現單點登錄,我對Oauth2.0比較推介,因爲它不僅在現有框架Spring Security下進行很好的實現,而且與其他技術的兼容性比較好,最重要的是Spring Cloud對它有現成的實現,搭建微服務認證中心非常合適。而CAS代碼實現是是通過一些零散的過濾器實現,而且對前後端分離不好實現。

CAS對各個子系統的資源請求進行認證處理,類似於Oauth2.0基於授權碼的授權模式,客戶端應用不接觸用戶的賬號密碼信息,只有認證中心能接受用戶的用戶名密碼等安全信息,其他系統不提供登錄入口,只接受認證中心的間接授權。而Oauth2.0提供的賬號密碼授權模式客戶端應用是接觸到用戶的安全信息的,但只適合對APP的認證處理。當用戶再次請求時,它們都需要通過認證中心驗證令牌的有效性,但是基於JWT的oauth2.0協議可以在令牌中取出用戶信息即可,省去了再次驗證信息

具體來講,有單機版的認證,多機版的認證,基於微服務的認證。
單機版的認證可以通過框架直接完成
多機版的認證可以通過Spring Security整合Oauth2.0協議,也可以整合CAS來實現,也可使用CAS單獨實現
微服務的認證其實就是基於網關的認證和授權,所有對微服務的請求都通過網關進行細粒度的控制,通過認證中心進行實際的認證和授權,網關除了解決認證和授權,還進行日誌收集和熔斷限流

cas基本流程

https://blog.csdn.net/anumbrella/category_7765386.html
在這裏插入圖片描述

首次登陸流程

  1. 首先用戶訪問系統1受保護的資源,系統1發現未登陸,跳轉至SSO認證中心
  2. SSO認證中心發現用戶未登錄,將用戶引導至登錄頁面
  3. 用戶輸入用戶名和密碼提交至SSO認證中心
  4. SSO認證中心校驗用戶信息,創建用戶與SSO認證中心之間的會全局會話,同時創建授權令牌
  5. SSO認證中心帶着令牌跳轉回最初的請求地址(系統1)
  6. 系統1拿到令牌,去SSO認證中心校驗令牌是否有效
  7. SSO認證中心校驗令牌,返回有效,註冊系統1的地址
  8. 系統1使用該令牌創建與用戶的會話,稱爲局部會話,返回給用戶受保護資源

再次登陸流程

  1. 用戶訪問系統2受保護的資源
  2. 系統2發現用戶未登錄,跳轉至SSO認證中心,並將自己的地址作爲參數傳遞過去
  3. SSO認證中心發現用戶已登錄,跳轉回系統2的地址,並附上令牌
  4. 系統2拿到令牌,去SSO認證中心校驗令牌是否有效
  5. SSO認證中心校驗令牌,返回有效,註冊系統2地址
  6. 系統2使用該令牌創建與用戶的局部會話,返回給用戶受保護資源

註銷流程

  1. 系統1根據用戶與系統1建立的會話id拿到令牌,向SSO認證中心發起註銷請求
  2. SSO認證中心校驗令牌有效,銷燬全局會話,同時取出所有用此令牌註冊的系統地址
  3. SSO認證中心向所有註冊系統發起註銷請求
  4. 各註冊系統接收SSO認證中心的註銷請求,銷燬局部會話
  5. SSO認證中心引導用戶至登錄頁面

TGC:用戶持有的令牌,表示成功登陸casClient web應用
TGT:CAS爲用戶簽發的全局令牌,構建全局會話
ST(TGT簽發):TGT簽發的某服務的令牌,構建局部會話
ST是TGT簽發的。用戶在CAS上認證成功後生成TGT,然後用TGT簽發一個ST,ST包含TGT屬性,然後redirect到客戶端應用

引入app的代理,爲用戶去申請PT,PT代表用戶成功登陸casClient app應用
a) PGT(ST簽發):代理服務持有的令牌,表示用戶成功登陸某一代理服務,可以代理應用爲其申請PT
b) PT:CAS爲用戶簽發的訪問app服務的令牌,表示成功登陸casClient app應用

cas實現相關

如果要驗證其他信息,比如郵箱,手機號,但是郵箱,手機信息在另一個數據庫,還有在一段時間內同一IP輸入錯誤次數限制等。這裏就需要我們自定義認證策略,自定義CAS的web認證流程
通過攔截請求獲取到Handler,來實現自定義認證策略

自定義登陸邏輯

  1. 通過繼承AbstractUsernamePasswordAuthenticationHandler實現用戶名密碼登陸,或者AbstractPreAndPostProcessingAuthenticationHandler實現其他數據的處理邏輯
  2. 通過繼承AuthenticationEventExecutionPlanConfigurer註冊自定義的認證邏輯

cas service配置

  1. 配置內容主要是:服務訪問配置,服務屬性配置,服務到期策略配置
  2. 配置存儲主要是:JSON file,Redis,JPA

cas service管理

  1. 啓用線程項目cas-management-overlay進行服務管理
  2. 自定義服務管理程序,通過實現ServiceManager接口

自定義用戶登陸界面

認證登陸頁面耦合於cas server

  1. 根據配置的cas service存儲方式,覆蓋默認的登陸界面
  2. 自定義驗證碼,使用Google的kaptcha類

SpringBoot配置cas client

  1. 配置攔截請求和退出的路徑,並注入自定義配置類
  2. 注入FilterRegistrationBean,然後通過它配置登陸認證過濾器,登出過濾器,ticket效驗過濾器,獲取登陸信息

SpringSecurity基本流程

認證流程

認證請求到達SecurityContextPersistenceFilter檢查是否有session,若有則直接返回登陸成功,否則進入UsernamePasswordFilter進行賬號密碼認證,它底層通過AuthenticationManager遍歷可用的AuthentcationProvider進行具體的認證操作,底層通過UserDetailsService根據用戶名稱獲取用戶信息與表單填入的進行匹配,若認證成功則將用戶信息放SecurityContextHolder

實現remember功能

UsernamePasswordAuthenticationFilter認證成功後,在成功處理器就會自動調用RememberMeService的方法創建token和用戶名一起存儲到數據庫中,然後將token寫到瀏覽器的Cookie中。
當用戶再次訪問系統時,被RememberMeAuthenticationFilter過濾器所攔截,它讀取cookie中的token,通過RememberService從數據庫中查出token對應的用戶名,然後通過UserDetailService再根據用戶名查詢用戶信息,最後放到SecuritContext裏。
在這裏插入圖片描述

圖形驗證碼效驗

  1. 自定義控制器生成圖形驗證碼,並生成圖片返回前端,然後將其保存到redis和session中
  2. 創建驗證碼過濾器,判斷用戶填寫的驗證碼和系統生成的驗證碼是否匹配,若不匹配則拋異常

短信驗證碼登陸效驗

  1. 自定義控制器生成短信驗證碼,將其發送給用戶,將驗證碼保存到redis或者session中
  2. 自定義過濾器攔截短信登陸請求,然後自定義AuthenticationProvider返回已認證Authentication
  3. 自定義短信驗證碼過濾器,判斷用戶填寫的短信驗證碼和存儲中的短信驗證嗎是否匹配,若不匹配則拋異常
    |——爲何不在provider進行匹配短信驗證碼呢??爲了使的驗證短信驗證碼這個流程可以複用,比如讓支付流程調用等
    |——有兩條線,一條是根據手機號進行身份認證(只保證系統中存在此用戶),另一條是驗證短信驗證碼是否匹配的邏輯

使用SpringSocial實現第三方登陸

  1. 用戶訪問客戶端前端,瀏覽器將請求導向認證服務器進行認證
  2. 用戶同意授權,攜帶授權碼返回給客戶端前端
  3. 客戶端後臺攜帶授權碼申請令牌
  4. 認證服務器發放令牌,客戶端後臺訪問服務提供商的用戶數據,攜帶令牌返回客戶端前端

Oauth2.0實現認證服務器

相比CAS,第三方

  1. Oauth生成令牌流程(認證服務器)
    客戶端應用向認證服務器申請令牌,TokenEndpoint通過ClientDetailsService從存儲中獲取註冊的第三方應用信息,然後將第三方用戶信息和用戶請求信息封裝爲Oauth2Authentication,AuthorizationServerTokenService創建Oatuth2AccessToken令牌,然後TokenStore將其存到某存儲器中
  2. Oauth效驗令牌流程(資源服務器)
    客戶端攜帶令牌訪問請求到達Oauth2AuthenticationProcessFilter,tokenExtractor從request中獲取Authentication,OAuth2AuthenticationManager通過tokenService查詢token對應的OAuth2Authentication對應,若登陸成功將Authentication放到SpringSecurityConetxt中。

Oauth2.0重構用戶名密碼登陸

在成功處理器中,封裝Oauth2Authentication,然後AuthorizationServerTokenService創建Oatuth2AccessToken令牌,然後TokenStore將其存到某存儲器中
在這裏插入圖片描述

基於Oauth2.0 jwt實現SSO

在這裏插入圖片描述

  1. 創建認證服務器,配置認證服務器客戶端信息,配置token存儲策略,配置tokenkey需要身份認證
  2. 創建rest服務器1,@EnableOauth2Sso,配置客戶端配置(客戶端信息,訪問認證服務器url,請求令牌url,獲取密鑰url)
  3. 創建rest服務器2,@EnableOauth2Sso,配置客戶端配置(客戶端信息,訪問認證服務器url,請求令牌url,獲取密鑰url)

Session管理

  1. session超時處理:server.session.timeout= 最少一分鐘,可配置失效處理控制器
  2. session併發控制
    用戶在其他瀏覽器登陸,踢掉前面那個:maximumSession(1)
    用戶不允許在其他地方登陸:maxSessionPreventLogin(true)
  3. 集羣session處理
    spring.session.store-type=REDIS
  4. 退出登陸
    訪問/logout後,當前session失效,清空remember-me記錄,清空securityConetxt,重定向到登錄頁
    logoutUrl()配置退出控制器,logoutSuccessHandler()配置退出重定向url,deleteCookies()刪除瀏覽器cookies

授權

系統配置信息:權限規則基本不變,antMatchers(方法,路由).hasRole(角色)
用戶權限信息 :權限規則靈活變化

SpringSecurity授權源碼流程

在這裏插入圖片描述
請求信息vs系統配置權限vs用戶擁有的權限——>AccessDecisionManager(策略)——>AccessDecisionVoter(WebExpressionVoter)多個投票者進行投票
SpringSecurity將權限轉換成一個權限表達式,然後通過WebExpressionVoter進行評估,只要有一個通過就通過
在這裏插入圖片描述
連用表達式
在這裏插入圖片描述

基於配置文件進行權限控制

  1. 只區分是否登錄or只區分簡單角色
  2. 權限規則基本不變

問題:在使用配置文件配置權限時,安全模塊事先並不知道業務模塊具體有哪些API需要權限控制,怎麼將配置信息進行全局管理呢???
在這裏插入圖片描述
AuthorizeConfigManager收集所有AuthorizeConfigProvider的實現,然後進行統一配置
在這裏插入圖片描述

基於角色的權限控制

角色衆多,隨着公司發展權限不斷變化

資源表(開發人員維護):菜單,按鈕及其URL
用戶表,角色表,用戶-角色表,角色-權限表
.access("@rbacService.hasPermission(request,authentication)")
.access("#rbacService.hasPermission(request,authentication)") //需要配置相應的權限表達式處理器

怎樣對接自己寫的權限模塊 和 SpringSecurity
a)定義一個RbacService接口,根據request和Authentication判斷是否有權限
b)實現授權服務方法,根據用戶名查詢所擁有權限的所有URL,只要有一個匹配request.getRequestURI()就判定權限通過
c)實現AuthorizeConfigProvider,將自己自定義的權限服務,以表達式的方式配置進去
d) 實現一個AuthorizeConfigManager,注入所有模塊的AuthorizeConfigProvider,然後將授權配置管理器配置到SecurityCofig默認配置

微服務環境基於網關的認證和授權

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章