javascript
jwt配置 restful_SpringBoot实现JWT保护前后端分离RESTful API
本文將用不到100行Java代碼, 教你如何在Spring Boot里面用JWT保護RESTful api.
登錄前
登錄之后即可得到正確結果
登陸后
1. 什么是JWT
了解JWT的同學可以跳過這一部分
廢話少說, 我們先看看什么是JWT. JSON Web Token其實就是一個包含認證數據的JSON, 大概長這樣子
分三個部分,
第一部分{"alg":"HS512"}是簽名算法
第二部分?{"exp":1495176357,"username":"admin"}是一些數據(你想放什么都可以), 這里有過期日期和用戶名
第三部分')4'7�6-DM�(�H6fJ::$c���a4�~tI2%Xd-�$nL(l非常重要,是簽名Signiture, 服務器會驗證這個以防偽造. 因為JWT其實是明文傳送, 任何人都能篡改里面的內容. 服務端通過驗證簽名, 從而確定這個JWT是自己生成的.
原理也不是很復雜, 我用一行代碼就能表示出來
首先我們將JWT第一第二部分的內容, 加上你的秘鑰(key或者叫secret), 然后用某個算法(比如hash算法)求一下, 求得的內容就是你的簽名. 驗證的時候只需要驗證你用JWT算出來的值是否等于JWT里面的簽名.
因為別人沒有你的key, 所以也就沒法偽造簽名.
簡單粗暴一行代碼解釋什么是簽名:
intsigniture =("{alg:HS512}{exp:1495176357,username:admin}"+key).hashCode();
最后附上簽名,得到完整的JWT:
{"alg":"HS512"}{"exp":1495176357,"username":"admin"}')4'7�6-DM�(�H6fJ::$c���a4�~tI2%Xd-�$nL(l
為了方便復制和使用, 通常我們都是把JWT用base64編碼之后放在http的header里面, 并且每一次呼叫api都附上這個JWT, 并且服務器每次也驗證JWT是否過期
通常我們用到的JWT:
Base64編碼后:eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE0OTUxNzYzNTcsInVzZXJuYW1lIjoiYWRtaW4ifQ.mQtCfLKfI0J7c3HTYt7kRN4AcoixiUSDaZv2ZKOjq2JMZjBhf1DmE0Fn6PdEkyJZhYZJTMLaIPwyR-uu6BMKGw
2. 三個class實現JWT
整個demo一共有三個class
Application.java JwtAuthenticationFilter.java 和 JwtUtil.java
2.1首先我們看一看Application.java
第一步創建一個hello world api
@GetMapping("/protected")public@ResponseBodyObjecthellWorld(){return"Hello World! This is a protected api";}
第二步創建一個 login的api, 我們會驗證用戶的密碼, 如果正確, 那么我們會返回生成jwt. 這時前端拿到的這個jwt就類似于拿到了一個臨時的密碼, 之后所有的HTTP RESTful api請求都附上這個"臨時密碼"即可.(專業術語叫令牌/token)
@PostMapping("/login")publicObjectlogin(HttpServletResponseresponse,@RequestBodyfinalAccountaccount)throwsIOException{if(isValidPassword(account)){Stringjwt =JwtUtil.generateToken(account.username);returnnewHashMap(){{put("token",jwt);}};}else{returnnewResponseEntity(HttpStatus.UNAUTHORIZED);}}
登錄效果如下圖
最后我們再注冊一個檢驗jwt的過濾器Filter, 通過這個過濾器Filter實現對每個Rest api請求都驗證jwt的功能. 這個JwtAuthenticationFilter繼承了OncePerRequestFilter, 任何請求都會先經過我們的filter, 然后我們會選擇讓那些有合法jwt的請求通過我們的filter.
@BeanpublicFilterRegistrationBeanjwtFilter(){finalFilterRegistrationBeanregistrationBean =newFilterRegistrationBean();JwtAuthenticationFilterfilter =newJwtAuthenticationFilter();registrationBean.setFilter(filter);returnregistrationBean;}
2.2然后我們看一下JwtAuthenticationFilter.java
這里我們繼承了OncePerRequestFilter, 保證了用戶請求任何資源都會運行這個doFilterInternal. 這里我們會從HTTP Header里面截取JWT, 并且驗證JWT的簽名和過期時間, 如果有問題, 我們會返回HTTP 401錯誤.
PS: 這里有個情況就是用戶登錄/login前是沒有jwt的, 所以我們要讓登錄的請求
publicclassJwtAuthenticationFilterextendsOncePerRequestFilter{//......一些不重要的代碼......@OverrideprotectedvoiddoFilterInternal(HttpServletRequestrequest,HttpServletResponseresponse,FilterChainfilterChain)throwsServletException,IOException{try{if(isProtectedUrl(request)){Stringtoken =request.getHeader("Authorization");//檢查jwt令牌, 如果令牌不合法或者過期, 里面會直接拋出異常, 下面的catch部分會直接返回JwtUtil.validateToken(token);}}catch(Exceptione){response.sendError(HttpServletResponse.SC_UNAUTHORIZED,e.getMessage());return;}//如果jwt令牌通過了檢測, 那么就把request傳遞給后面的RESTful apifilterChain.doFilter(request,response);}//......一些不重要的代碼......}
2.3最后我們看一下JwtUtil.java
這里就兩個函數, 第一個函數生成一個有效期1000小時的jwt
public static String generateToken(String username)
第二個函數是驗證JWT是否有效, 如果JWT有效則返回用戶名, 否則拋出Exception
public static void validateToken(String token)
這里的代碼都非常簡潔就十幾行, 使用的都是現成的包, 建議直接看源代碼.
3.測試
這就是呼叫api的效果
正確jwt
總結
以上是生活随笔為你收集整理的jwt配置 restful_SpringBoot实现JWT保护前后端分离RESTful API的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么在 iPhone 中删除的照片,在
- 下一篇: 中国联通网上营业厅(《中国》第一季)