1. 程式人生 > >Spring Security、實現圖形驗證碼功能、實現"記住我"功能

Spring Security、實現圖形驗證碼功能、實現"記住我"功能

說在前面

博主最近會有很多專案跟大家一起分享,做完後會上傳github上的,希望讀友們能給博主提提意見哈哈

這個專案是第三方登入和安全方面的,關於後臺與app和網站的登入連線操作的實戰專案

各位如果可以就給我star哈哈謝謝啦

Spring Security

使用Spring Security開發基於表單的認證

核心功能:
  • 認證(你是誰)
  • 授權(你能幹什麼)
  • 攻擊防護(防止偽造身份)

SpringSecurity基本原理

第一步:請求提交 第二步:過濾器鏈去認證 第三步:到達FilterSecurityInterceptor進行最後一層驗證(這裡可以作VIP和普通使用者的認證,如果這裡認證失敗,則丟擲異常,傳遞到ExecptionTranslationFilter進行解析) 第四步:ExecptionTranslationFilter解析出認證失敗的地方,傳回過濾器鏈中對應的Filter進行認證處理 第五步:認證成功的話呼叫服務端的REST API

自定義使用者認證邏輯

處理使用者資訊獲取邏輯
處理使用者校驗邏輯
  • UserDetailsService
處理密碼加密解密
  • PasswordEncoder
  • 同樣的密碼每次加密出來的結果都是不一樣的
  • 處理流程:註冊時進行passwordEncoder.encode(密碼)加密->存入資料庫->登入時認證->取出資料庫裡的密碼(加密過的)->比較,加密串中含隨機生成的鹽,判斷的時候通過隨機生成的鹽反推回去

個性化使用者認證流程

自定義登入頁面
  • http.formLogin().loginPage(“/tihom-signIn.html”)
  • 在application中做配置跳轉頁面,如果沒有配置則跳轉到預設的登入頁面
  • 定義一個系統配置項SecurityProperties,它裡面包含BrowserProperties這個配置項,與browser有關的屬性都會配置在這個BrowserProperties中
  • 在SecurityProperties上配置@ConfigurationProperties(prefix = “tihom.security”),意思是這個類會讀取整個系統中以tihom.security開頭的配置
  • 定義一個SecurityCoreConfig核心配置類,在它上面配置@Configuration和@EnableConfigurationProperties(SecurityProperties.class),配置配置讀取器,讓這些類生效

這裡寫圖片描述 這裡寫圖片描述

自定義登入成功處理

  • 實現介面AuthenticationSuccessHandler,定義為元件
  • 在BrowserSecurityConfig中配置successHandler()處理器
  • 每日簽到
  • 積分記錄

自定義登入失敗處理

  • 同理

認證流程原始碼級詳解

認證處理流程說明
  • 1.進入UsernamePasswordAuthenticationFilter 這裡寫圖片描述 這裡寫圖片描述 這裡寫圖片描述
  • 2.AuthenticationManager,這是管理AuthenticationProvider的,拿到上一步傳入的token後,遍歷AuthenticationProvider去找到合適的認證邏輯,挨個詢問是否支援這個token所需求的登入方式
  • 3.進入xxxAuthenticationProvider(繼承AbstractUserDetailsAuthenticationProvider)去處理認證->retrieveUser()方法->UserDetailsService->UserDetails(資料庫中拿出來的使用者資訊)->preAuthenticationChecks(預檢查),檢查使用者是否鎖定、檢查使用者是否過期->additionalAuthenticationChecks(附加的檢查),如校驗密碼是否匹配等->postAuthenticationChecks(後檢查)
  • 4.createSuccessAuthentication->new UsernamePasswordAuthenticationToken(三個引數的建構函式,因為此時已經認證了,setAuthenticated(true))

這裡寫圖片描述

認證結果如何在多個請求之間共享

  • SecurityContextPersistenceFilter:在整個過濾器鏈的最前面,請求先經過它,檢查session裡面是否有SecurityContext,有就把SecurityContext拿出來放到ThreadLocal執行緒裡,沒有就空的過去了;當整個請求響應回來之後再次經過的時候,它檢查執行緒,如果執行緒裡面有SecurityContext就拿出來放到session裡面去.這樣不同的請求就可以同一個session裡面拿到相同的使用者認證資訊,拿到以後放到執行緒裡面,因為整個的請求和響應的過程都在一個執行緒裡完成的,所以線上程的其他位置隨時可以通過SecurityContextHolder來拿到使用者資訊

這裡寫圖片描述

獲取認證使用者資訊

  • 在UserController中
@GetMapping("/me")
    public Object getCurrentUser(@AuthenticationPrincipal UserDetails user/* Authentication authentication*/){
//        return SecurityContextHolder.getContext().getAuthentication();
        //Spring會自動去SecurityContext物件裡去找
//        return authentication;
        return user;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

實現圖形驗證碼功能

開發生成圖形驗證碼介面
  • 根據隨機數生成圖片
  • 將隨機數存到session中
  • 將生成的圖片寫到介面的響應中
在認證流程中加入圖形驗證碼校驗
重構圖形驗證碼介面

這裡寫圖片描述

1.驗證碼基本引數可配置

應用級配置 * 將驗證碼的大小等基本引數,定義一個驗證碼圖片配置類和一個驗證配置類,前者繼承於後者 * 在SecutiryProperties中配置驗證配置類 * 這樣在application.properties中就可以作全域性配置了 請求級的配置 * 在控制器中配置Generator的實現

2.驗證碼攔截的介面可配置

多個請求都需要驗證圖形驗證碼

3.驗證碼的生成邏輯可配置

把驗證碼生成的邏輯轉移到一個ImageCodeGenerator發生器 在ValidateCodeBeanConfig中配置ValidateCodeGenerator

最後基本邏輯是:ValidateCodeBeanConfig配置類->ValidateCodeGenerator介面->ImageCodeGenerator介面實現類(含SecurityProperties)->ValidateCodeController控制器(呼叫ValidateCodeGenerator介面,但是使用的是imageCodeGenerator)->生成驗證碼

實現”記住我”功能

記住我功能的基本原理

這裡寫圖片描述

記住我功能的具體實現

在BrowserProperties中配置過期時間 瀏覽器配置類中新增persistentTokenRepository 在configure中配置

.rememberMe()
    .tokenRepository(persistentTokenRepository())
    .tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())
    .userDetailsService(userDetailsService)
  • 1
  • 2
  • 3
  • 4

記住我功能SpringSecurity原始碼解析

進入UsernamePasswordAuthenticationFilter->進入AbstractAuthenticationProcessingFilter(呼叫rememberMeServices服務)->onLoginSuccess(用tokenRepository建立新的token,新增到cookie中)

->到這裡登入完成

下次登入
進入RememberMeAuthenticationFilter(呼叫rememberMeServices的autoLogin方法)->從請求的cookie中拿到token和series,然後根據series值去資料庫裡拿token和使用者資訊->作判斷->UserDetailsService呼叫戶資訊->SecurityContextHolder.getContext().setAuthentication(rememberMeAuth)把使用者資訊放入session裡

說在前面

博主最近會有很多專案跟大家一起分享,做完後會上傳github上的,希望讀友們能給博主提提意見哈哈

這個專案是第三方登入和安全方面的,關於後臺與app和網站的登入連線操作的實戰專案

各位如果可以就給我star哈哈謝謝啦

Spring Security

使用Spring Security開發基於表單的認證

核心功能:
  • 認證(你是誰)
  • 授權(你能幹什麼)
  • 攻擊防護(防止偽造身份)

SpringSecurity基本原理

第一步:請求提交 第二步:過濾器鏈去認證 第三步:到達FilterSecurityInterceptor進行最後一層驗證(這裡可以作VIP和普通使用者的認證,如果這裡認證失敗,則丟擲異常,傳遞到ExecptionTranslationFilter進行解析) 第四步:ExecptionTranslationFilter解析出認證失敗的地方,傳回過濾器鏈中對應的Filter進行認證處理 第五步:認證成功的話呼叫服務端的REST API

自定義使用者認證邏輯

處理使用者資訊獲取邏輯
處理使用者校驗邏輯
  • UserDetailsService
處理密碼加密解密
  • PasswordEncoder
  • 同樣的密碼每次加密出來的結果都是不一樣的
  • 處理流程:註冊時進行passwordEncoder.encode(密碼)加密->存入資料庫->登入時認證->取出資料庫裡的密碼(加密過的)->比較,加密串中含隨機生成的鹽,判斷的時候通過隨機生成的鹽反推回去

個性化使用者認證流程

自定義登入頁面
  • http.formLogin().loginPage(“/tihom-signIn.html”)
  • 在application中做配置跳轉頁面,如果沒有配置則跳轉到預設的登入頁面
  • 定義一個系統配置項SecurityProperties,它裡面包含BrowserProperties這個配置項,與browser有關的屬性都會配置在這個BrowserProperties中
  • 在SecurityProperties上配置@ConfigurationProperties(prefix = “tihom.security”),意思是這個類會讀取整個系統中以tihom.security開頭的配置
  • 定義一個SecurityCoreConfig核心配置類,在它上面配置@Configuration和@EnableConfigurationProperties(SecurityProperties.class),配置配置讀取器,讓這些類生效

這裡寫圖片描述 這裡寫圖片描述

自定義登入成功處理

  • 實現介面AuthenticationSuccessHandler,定義為元件
  • 在BrowserSecurityConfig中配置successHandler()處理器
  • 每日簽到
  • 積分記錄

自定義登入失敗處理

  • 同理

認證流程原始碼級詳解

認證處理流程說明
  • 1.進入UsernamePasswordAuthenticationFilter 這裡寫圖片描述 這裡寫圖片描述 這裡寫圖片描述
  • 2.AuthenticationManager,這是管理AuthenticationProvider的,拿到上一步傳入的token後,遍歷AuthenticationProvider去找到合適的認證邏輯,挨個詢問是否支援這個token所需求的登入方式
  • 3.進入xxxAuthenticationProvider(繼承AbstractUserDetailsAuthenticationProvider)去處理認證->retrieveUser()方法->UserDetailsService->UserDetails(資料庫中拿出來的使用者資訊)->preAuthenticationChecks(預檢查),檢查使用者是否鎖定、檢查使用者是否過期->additionalAuthenticationChecks(附加的檢查),如校驗密碼是否匹配等->postAuthenticationChecks(後檢查)
  • 4.createSuccessAuthentication->new UsernamePasswordAuthenticationToken(三個引數的建構函式,因為此時已經認證了,setAuthenticated(true))

這裡寫圖片描述

認證結果如何在多個請求之間共享

  • SecurityContextPersistenceFilter:在整個過濾器鏈的最前面,請求先經過它,檢查session裡面是否有SecurityContext,有就把SecurityContext拿出來放到ThreadLocal執行緒裡,沒有就空的過去了;當整個請求響應回來之後再次經過的時候,它檢查執行緒,如果執行緒裡面有SecurityContext就拿出來放到session裡面去.這樣不同的請求就可以同一個session裡面拿到相同的使用者認證資訊,拿到以後放到執行緒裡面,因為整個的請求和響應的過程都在一個執行緒裡完成的,所以線上程的其他位置隨時可以通過SecurityContextHolder來拿到使用者資訊

這裡寫圖片描述

獲取認證使用者資訊

  • 在UserController中
@GetMapping("/me")
    public Object getCurrentUser(@AuthenticationPrincipal UserDetails user/* Authentication authentication*/){
//        return SecurityContextHolder.getContext().getAuthentication();
        //Spring會自動去SecurityContext物件裡去找
//        return authentication;
        return user;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

實現圖形驗證碼功能

開發生成圖形驗證碼介面
  • 根據隨機數生成圖片
  • 將隨機數存到session中
  • 將生成的圖片寫到介面的響應中
在認證流程中加入圖形驗證碼校驗
重構圖形驗證碼介面

這裡寫圖片描述

1.驗證碼基本引數可配置

應用級配置 * 將驗證碼的大小等基本引數,定義一個驗證碼圖片配置類和一個驗證配置類,前者繼承於後者 * 在SecutiryProperties中配置驗證配置類 * 這樣在application.properties中就可以作全域性配置了 請求級的配置 * 在控制器中配置Generator的實現

2.驗證碼攔截的介面可配置

多個請求都需要驗證圖形驗證碼

3.驗證碼的生成邏輯可配置

把驗證碼生成的邏輯轉移到一個ImageCodeGenerator發生器 在ValidateCodeBeanConfig中配置ValidateCodeGenerator

最後基本邏輯是:ValidateCodeBeanConfig配置類->ValidateCodeGenerator介面->ImageCodeGenerator介面實現類(含SecurityProperties)->ValidateCodeController控制器(呼叫ValidateCodeGenerator介面,但是使用的是imageCodeGenerator)->生成驗證碼

實現”記住我”功能

記住我功能的基本原理

這裡寫圖片描述

記住我功能的具體實現

在BrowserProperties中配置過期時間 瀏覽器配置類中新增persistentTokenRepository 在configure中配置

.rememberMe()
    .tokenRepository(persistentTokenRepository())
    .tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())
    .userDetailsService(userDetailsService)
  • 1
  • 2
  • 3
  • 4

記住我功能SpringSecurity原始碼解析

進入UsernamePasswordAuthenticationFilter->進入AbstractAuthenticationProcessingFilter(呼叫rememberMeServices服務)->onLoginSuccess(用tokenRepository建立新的token,新增到cookie中)

->到這裡登入完成

下次登入
進入RememberMeAuthenticationFilter(呼叫rememberMeServices的autoLogin方法)->從請求的cookie中拿到token和series,然後根據series值去資料庫裡拿token和使用者資訊->作判斷->UserDetailsService呼叫戶資訊->SecurityContextHolder.getContext().setAuthentication(rememberMeAuth)把使用者資訊放入session裡