SpringSecurity代碼實現JWT接口權限授予與校驗

2021-01-13 字母哥博客

通過筆者前兩篇文章的說明,相信大家已經知道JWT是什麼,怎麼用,該如何結合Spring Security使用。那麼本節就用代碼來具體的實現一下JWT登錄認證及鑑權的流程。為了大部分的移動端用戶觀看,本文所有代碼均用圖片的形式發布,圖片點擊可放大。

一、環境準備工作

建立Spring Boot項目併集成了Spring Security,項目可以正常啟動

通過controller寫一個HTTP的GET方法服務接口,比如:「/hello」

實現最基本的動態數據驗證及權限分配,即實現UserDetailsService接口和UserDetails接口。這兩個接口都是向Spring Security提供用戶、角色、權限等校驗信息的接口

如果你學習過Spring Security的formLogin登錄模式,請將HttpSecurity配置中的formLogin()配置段全部去掉。因為JWT完全使用JSON接口,沒有from表單提交。

HttpSecurity配置中一定要加上csrf().disable(),即暫時關掉跨站攻擊CSRF的防禦。這樣是不安全的,我們後續章節再做處理。

以上的內容,我們在之前的文章中都已經講過。如果仍然不熟悉,可以翻看本號之前的文章。

二、開發JWT工具類

通過maven坐標引入JWT工具包jjwt

圖片:JWT工具包maven坐標

在application.yml中加入如下自定義一些關於JWT的配置

jwt: header: JWTHeaderName secret: aabbccdd expiration: 3600000

其中header是攜帶JWT令牌的HTTP的Header的名稱。雖然我這裡叫做JWTHeaderName,但是在實際生產中可讀性越差越安全。

secret是用來為JWT基礎信息加密和解密的密鑰。雖然我在這裡在配置文件寫死了,但是在實際生產中通常不直接寫在配置文件裡面。而是通過應用的啟動參數傳遞,並且需要定期修改。

expiration是JWT令牌的有效時間。

寫一個Spring Boot配置自動加載的工具類。

圖片:開發JWT工具類

上面的代碼就是使用io.jsonwebtoken.jjwt提供的方法開發JWT令牌生成、刷新的工具類。

三、開發登錄接口(獲取Token的接口)

"/authentication"接口用於登錄驗證,並且生成JWT返回給客戶端

"/refreshtoken"接口用於刷新JWT,更新JWT令牌的有效期

圖片:開發登錄接口(獲取Token的接口)

核心的token業務邏輯寫在JwtAuthService 中

login方法中首先使用用戶名、密碼進行登錄驗證。如果驗證失敗拋出BadCredentialsException異常。如果驗證成功,程序繼續向下走,生成JWT響應給前端

refreshToken方法只有在JWT token沒有過期的情況下才能刷新,過期了就不能刷新了。需要重新登錄。

圖片:核心的token業務邏輯寫在JwtAuthService 中

因為使用到了AuthenticationManager ,所以在繼承WebSecurityConfigurerAdapter的SpringSecurity配置實現類中,將AuthenticationManager 聲明為一個Bean。並將"/authentication"和 "/refreshtoken" 開放訪問權限,如何開放訪問權限,我們之前的文章已經講過了。

@Bean(name = BeanIds.AUTHENTICATION_MANAGER)@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean();}

四、接口訪問鑑權過濾器

當用戶第一次登陸之後,我們將JWT令牌返回給了客戶端,客戶端應該將該令牌保存起來。在進行接口請求的時候,將令牌帶上,放到HTTP的header裡面,header的名字要和jwt.header的配置一致,這樣服務端才能解析到。下面我們定義一個攔截器:

攔截接口請求,從請求request獲取token,從token中解析得到用戶名

然後通過UserDetailsService獲得系統用戶(從資料庫、或其他其存儲介質)

根據用戶信息和JWT令牌,驗證系統用戶與用戶輸入的一致性,並判斷JWT是否過期。如果沒有過期,至此表明了該用戶的確是該系統的用戶。

但是,你是系統用戶不代表你可以訪問所有的接口。所以需要構造UsernamePasswordAuthenticationToken傳遞用戶、權限信息,並將這些信息通過authentication告知Spring Security。Spring Security會以此判斷你的接口訪問權限。

圖片:接口訪問鑑權過濾器

在spring Security的配置類(即WebSecurityConfigurerAdapter實現類的configure(HttpSecurity http)配置方法中,加入如下配置:

.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and().addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

因為我們使用了JWT,表明了我們的應用是一個前後端分離的應用,所以我們可以開啟STATELESS禁止使用session。當然這並不絕對,前後端分離的應用通過一些辦法也是可以使用session的,這不是本文的核心內容不做贅述。

將我們的自定義jwtAuthenticationTokenFilter,加載到UsernamePasswordAuthenticationFilter的前面。

五、PostMan測試一下:

測試登錄接口,即:獲取token的接口。輸入正確的用戶名、密碼即可獲取token。

圖片:測試登錄接口

下面我們訪問一個我們定義的簡單的接口「/hello」,但是不傳遞JWT令牌,結果是禁止訪問。當我們將上一步返回的token,傳遞到header中,就能正常響應hello的接口結果。

圖片:訪問接口「/hello」

通過zimug點靠m,更多精品合集知識等待你! 本號只做持續的知識輸出,希望您能關注、評論、轉發!您的支持是我不竭的創作動力!讓知識產生價值、讓程式設計師改變世界!

相關焦點

  • SpringSecurity + JWT前後端分離架構實現
    比如:集群應用,同一個應用部署甲、乙、丙三個主機上,實現負載均衡應用,其中一個掛掉了其他的還能負載工作。要知道session是保存在伺服器內存裡面的,三個主機一定是不同的內存。那麼你登錄的時候訪問甲,而獲取接口數據的時候訪問乙,就無法保證session的唯一性和共享性。當然以上的這些情況我們都有方案(如redis共享session等),可以繼續使用session來保存狀態。
  • Spring Security OAuth2.0認證授權五:用戶信息擴展到jwt
    註:本文章基於原始碼https://gitee.com/kdyzm/spring-security-oauth-study/tree/v5.0.0 分析和改造。一、實現UserDetailsService接口1.問題分析和修改jwt令牌中用戶信息過於少的原因在於認證服務auth-server中com.kdyzm.spring.security.auth.center.service.MyUserDetailsServiceImpl#loadUserByUsername 方法中的這段代碼return User
  • Spring boot + Spring Security實現權限管理
    上圖代碼分三段理解:1.配置認證,開啟formLogin模式;2.配置權限;3.禁用跨站csrf攻擊防禦。根據權限配置,user用戶可以訪問訂單頁面,不能訪問用戶管理、角色管理和菜單管理,下面我們分別訪問訂單頁面和用戶管理頁面,看一下是不是和我們的代碼配置一致。
  • 利用jwt 可以獲取用戶的額外信息?
    涉及的小問題有以下三個:如何在返回的 jwt 中添加自定義數據;如何在 jwt 中添加用戶的額外數據,比如用戶 id、手機號碼;如何在資源伺服器中取出這些自定義數據。下面我們分別來看如何實現。如何在返回的 jwt 中添加自定義數據這個問題比較簡單,只要按照如下兩步即可:1.
  • (建議收藏)|Spring Boot集成JSON Web Token(JWT)
    ## 1.2 基於token認證token原理:使用用戶名和密碼請求登錄接口登錄接口驗證用戶名和密碼登錄接口生成一個uuid作為token,將用戶信息作為值,然後保存到redis緩存中jedis.set(token, user);登錄接口返回用戶信息和token瀏覽器將token保存到本地當請求其它接口時就攜帶token值接口根據token去緩存中查,如果找到了就調用接口
  • Spring中這些能升華代碼的技巧,可能會讓你愛不釋手
    假如有權限認證、日誌、統計的場景,可以使用該攔截器。request.getRequestURI();         if (checkAuth(requestUrl)) {             return  true;         }          return  false;     }      private boolean checkAuth(String requestUrl) {         System.out.println("===權限校驗
  • 入門|egg.js 入門之egg-jwt
    "123456"//自定義 token 的加密條件字符串};config.security = { csrf: { enable: false, ignoreJSON: true }, domainWhiteList: ['http://localhost:8080'],//允許訪問接口的白名單};config.cors = { origin:'*', allowMethods
  • SpringSecurity框架下實現CSRF跨站攻擊防禦
    SpringSecurity框架下實現CSRF跨站攻擊防禦本文是Spring Security系列中的一篇,如果你想學習JWT、OAuth2及網際網路應用登錄認證、接口鑑權設計、實現方法,希望能關注我!本號已經寫了十幾篇Spring Security文章。還會繼續寫!
  • SpringSecurity 默認表單登錄頁展示流程源碼
    控制臺會列印一個 seuciryt password : xxxUsing generated security password: f520875f-ea2b-4b5d-9b0c-f30c0c17b90b直接登錄用戶名:user 密碼 :
  • uliweb_apijson 0.1.2 發布,自動化接口和文檔 Python 實現
    uliweb-apijson is a subset and slightly different variation of apijsonYou can try:uliweb-apijson 是 APIJSON 的 Python 版後端實現,基於 uliweb 框架。
  • JWT 使用 nimbus-jose-jwt 進行解碼
    在程序中獲得 JWT 的Token 代碼後,可以對 JWT 進行解碼。常用的可以使用 OAuth0 提供的解碼包,你也可能會使用 nimbus-jose-jwt 包。然後將這個 JWT 轉換為 SignedJWTSignedJWT sjwt = SignedJWT.parse(token);然後你可以使用下面的代碼獲得所有的 claims。nimbus-jose-jwt 返回的結果是 set。隨後你就可以根據返回的 Set 去查詢你需要的內容了。
  • Spring Cloud 中 Zuul 網關到底有何牛逼之處?竟然這麼多人在用!
    使用Zuul,一般在微服務數量較多(多於10個)的時候推薦使用,對服務的管理有嚴格要求的時候推薦使用,當微服務權限要求嚴格的時候推薦使用。一、Zuul網關的作用網關有以下幾個作用:統一入口:未全部為服務提供一個唯一的入口,網關起到外部和內部隔離的作用,保障了後臺服務的安全性。鑑權校驗:識別每個請求的權限,拒絕不符合要求的請求。
  • 14個編寫Spring MVC控制器的實用小技巧
    2.實現控制器接口在Spring MVC中創建控制器還可以用另一個經典的方法,即對一個類實現Controller接口。這是一個將控制器從ServletAPI的HttpServletRequest接口中解耦出來的好方法。
  • 乾貨丨Python接口測試自動化實戰及代碼示例:含get、post等方法
    接著在 test_jiafa 方法中,我們對剛才 jiafa 函數進行了和值校驗。通過給 jiafa 輸入兩個值,獲取其函數返回值,並與真實值做相等判斷,以此實現函數單元測試。對於接口來說,往往需要傳入很多參數,並且這每個參數又有很多取值,如果不對原先的 unittest 框架做改變,不僅無法用來進行接口測試,而且一個個結合參數取值去寫測試代碼,工作量極其龐大,也沒有實現測試數據與腳本沒有分離。基於此,我們對該框架做出一下兩點優化。
  • 如何實現IPC內嵌TMS320F206電錶校驗的接口?
    在進行常規電量測量裝置的校驗中,作為校驗裝置,一定要對電壓、電流的幅值、頻率、相位等進行高精度測量,在校驗裝置中採用TI公司DSP器件TMS320F206控制A/D轉換、數據採集和數字濾波處理,並把濾波處理後的數據傳送給微機進行數據的進一步處理,實現了高精度電錶校驗的要求
  • 基於Spring Boot + MVC 之控制器Controller實現
    寫在前面,首先我們要有一個Spring Boot的項目工程,查看 通過Idea創建Spring Boot java項目,先建立一個Spring Boot的項目工程,以下內容將在之前的demo基礎上,實現通過url向後臺請求一個學生名稱。
  • JWT:你好了解一下 只要兩分鐘!
    1、傳統的session認證因為HTTP協議本身是無狀態的,而在本次會話過程中我們的每一次請求都需要進行用戶身份認證的保持,於是將第一次請求服務端校驗後的用戶身份標誌(session_id)保存在客戶端(cookie)便於下次請求時帶上身份,這樣服務端就能識別身份了。借用一個圖片來理解。
  • 自動化接口和文檔 APIJSON 3.0.0 發布
    在線解析自動生成文檔,清晰可讀永遠最新自動生成請求代碼,支持Android和iOS自動生成JavaBean文件,一鍵下載自動管理與測試接口用例,一鍵共享自動校驗與格式化JSON,支持高亮和收展對於前端不用再向後端催接口、求文檔數據和結構完全定製,要啥有啥
  • Spring Boot 2.4 第一個示例程序書寫代碼
    在默認情況下,Maven 會編譯 src/main/java 目錄中的原始碼(這個是與 Maven 使用的約定有關的,這個目錄結構可以修改,但是不建議修改,因為絕大部分人都會遵守這個約定)。根據 Maven 的原始碼約定,你需要按照下面的目錄路徑和文件名創建一個 Example.java 文件,完整的路徑如下: src/main/java/Example.java 。