spring boot jwt_springboot整合JWT
springboot整合JWT
一、JWT介紹
JSON Web token簡稱JWT, 是用于對應用程序上的用戶進行身份驗證的標記。也就是說, 使用 JWTS 的應用程序不再需要保存有關其用戶的 cookie 或其他session數據。此特性便于可伸縮性, 同時保證應用程序的安全。
在身份驗證過程中, 當用戶使用其憑據成功登錄時, 將返回 JSON Web token, 并且必須在本地保存 (通常在本地存儲中)。每當用戶要訪問受保護的路由或資源 (端點) 時, 用戶代理(user agent)必須連同請求一起發送 JWT, 通常在授權標頭中使用Bearer schema。后端服務器接收到帶有 JWT 的請求時, 首先要做的是驗證token。
1.JWT的格式
JWT就是一個字符串,經過加密處理與校驗處理的字符串,形式為:A.B.C,第一部分我們稱它為頭部(header),第二部分我們稱其為載荷(payload, 類似于飛機上承載的物品),第三部分是簽證(signature).
A由JWT頭部信息header加密得到
B由JWT用到的身份驗證信息json數據加密得到
C由A和B加密得到,是校驗部分
2.怎樣使用token?
可以放到HTTP請求的請求頭中,通常是Authorization字段。
3.流程圖
二、java代碼實現
springboot經典的四個步驟1.改pom2.寫yml/properties3.啟動類4.代碼1.maven依賴
<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.1</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>2.配置application.properties
沒用這個里面的
server.port=8087 # 要加密的明文 jwt.secret=hand2020 # tocken 過期時間,單位秒 jwt.expire=3003.啟動類
這里選擇使用@ServletComponentScan,是因為在Filter類用@component和@configuration會導致
@WebFilter(urlPatterns = “/testToken”, filterName = “jwtFilter”) url失效變成攔截所有
package com.example.bootjwt;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan;@SpringBootApplication @ServletComponentScan //這里是將filter掃描加載進spring容器 public class BootJwtApplication {public static void main(String[] args) {SpringApplication.run(BootJwtApplication.class, args);}}4.實現代碼
這里主要是做一個簡單的demo驗證,有三個類JwtController、CreatToken、JwtFilter。
JwtController:用來接收rest請求。
JwtUtil:用來生成token,解密token,驗證token
JwtFilter:用來攔截請求對http請求中攜帶的token進行驗證
JwtController
package com.example.bootjwt.controller;import com.example.bootjwt.Util.JwtUtil; import com.example.bootjwt.domain.User; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;@RestController public class JwtController {@PostMapping("/get")public String creatToken2(){User user = new User();user.setId("1");user.setUsername("hand2020");user.setPassword("123456");return JwtUtil.createJWT(40000,user);}@PostMapping("/test")public String testToken2(HttpServletRequest request, HttpServletResponse response){String token= request.getHeader("Authorization");User user = new User();user.setId("1");user.setUsername("hand2020");user.setPassword("123456");if (JwtUtil.isVerify(token,user)){return "success";}return "fail";} }JwtUtil
這里我是在配置文件中讀需要加密的明文,和過期時間。也可以在controller里處理參數設置。
package com.example.bootjwt.Util;import com.example.bootjwt.domain.User; import io.jsonwebtoken.*; import org.springframework.beans.factory.annotation.Value;import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.UUID;public class JwtUtil {// @Value("${jwt.secret}") // private static String key;/*** 用戶登錄成功后生成Jwt* 使用Hs256算法 私匙使用用戶密碼** @param ttlMillis jwt過期時間* @param user 登錄成功的user對象* @return*/public static String createJWT(long ttlMillis, User user) {//指定簽名的時候使用的簽名算法,也就是header那部分,jjwt已經將這部分內容封裝好了。SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;//生成JWT的時間long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis);//創建payload的私有聲明(根據特定的業務需要添加,如果要拿這個做驗證,一般是需要和jwt的接收方提前溝通好驗證方式的)Map<String, Object> claims = new HashMap<String, Object>();claims.put("id", user.getId());claims.put("username", user.getUsername());claims.put("password", user.getPassword());//生成簽名的時候使用的秘鑰secret,這個方法本地封裝了的,一般可以從本地配置文件中讀取,切記這個秘鑰不能外露哦。它就是你服務端的私鑰,在任何場景都不應該流露出去。一旦客戶端得知這個secret, 那就意味著客戶端是可以自我簽發jwt了。String key = user.getPassword();//生成簽發人String subject = user.getUsername();//下面就是在為payload添加各種標準聲明和私有聲明了//這里其實就是new一個JwtBuilder,設置jwt的bodyJwtBuilder builder = Jwts.builder()//如果有私有聲明,一定要先設置這個自己創建的私有的聲明,這個是給builder的claim賦值,一旦寫在標準的聲明賦值之后,就是覆蓋了那些標準的聲明的.setClaims(claims)//設置jti(JWT ID):是JWT的唯一標識,根據業務需要,這個可以設置為一個不重復的值,主要用來作為一次性token,從而回避重放攻擊。.setId(UUID.randomUUID().toString())//iat: jwt的簽發時間.setIssuedAt(now)//代表這個JWT的主體,即它的所有人,這個是一個json格式的字符串,可以存放什么userid,roldid之類的,作為什么用戶的唯一標志。.setSubject(subject)//設置簽名使用的簽名算法和簽名使用的秘鑰.signWith(signatureAlgorithm, key);if (ttlMillis >= 0) {long expMillis = nowMillis + ttlMillis;Date exp = new Date(expMillis);//設置過期時間builder.setExpiration(exp);}return builder.compact();}/*** Token的解密* @param token 加密后的token* @param user 用戶的對象* @return*/public static Claims parseJWT(String token, User user) {//簽名秘鑰,和生成的簽名的秘鑰一模一樣String key = user.getPassword();//得到DefaultJwtParserClaims claims = Jwts.parser()//設置簽名的秘鑰.setSigningKey(key)//設置需要解析的jwt.parseClaimsJws(token).getBody();return claims;}/*** 校驗token* 在這里可以使用官方的校驗,我這里校驗的是token中攜帶的密碼于數據庫一致的話就校驗通過* @param token* @param user* @return*/public static Boolean isVerify(String token, User user) {//簽名秘鑰,和生成的簽名的秘鑰一模一樣String key = user.getPassword();//Jwts.parser在執行parseClaimsJws(token)時如果token時間過期會拋出ExpiredJwtException異常try {//得到DefaultJwtParserClaims claims = Jwts.parser()//設置簽名的秘鑰.setSigningKey(key)//設置需要解析的jwt.parseClaimsJws(token).getBody();if (claims.get("password").equals(user.getPassword())) {return true;}}catch (ExpiredJwtException e){e.printStackTrace();}return false;}}JwtFilter
過濾器是通過實現Filter接口,注意@WebFilter相當于xml配置,但是需要在啟動類上注解
@ServletComponentScan,將JwtFilter加入到spring容器中。
在JwtFilter類上注解@component或@configuration會導致@WebFilter失效從而攔截所有請求
目前這個沒用到,直接在controller里做了判斷,這個是后續業務需求的demo
package com.example.bootjwt;import com.example.bootjwt.Util.JwtUtil; import com.example.bootjwt.domain.User; import org.springframework.beans.factory.annotation.Autowired;import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebFilter(urlPatterns = "/testToken", filterName = "jwtFilter") public class JwtFilter implements Filter {@Autowiredprivate CreatToken creatToken;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest)servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;response.setCharacterEncoding("UTF-8");response.setContentType("application/json; charset=utf-8");response.setHeader("Access-Control-Allow-Origin", "*");String token= request.getHeader("Authorization");User user = new User();user.setId("1");user.setUsername("hand2020");user.setPassword("123456");boolean flag = JwtUtil.isVerify(token,user);if (flag){filterChain.doFilter(servletRequest,servletResponse);}else {System.out.println("失敗。。。。。。。。");response.getWriter().write("失敗。。。。。。。。");}}@Overridepublic void destroy() {} }##三、 測試效果
由于沒有寫前端代碼,就用postman模擬請求
1.瀏覽器發送請求獲取token
http://localhost:8087/get
2.將token放入請求頭中請求
注意將上次請求獲得的token放入請求頭內(注意不要過太長時間因為token設置了40秒過期)http://localhost:8087/test
token超時:
總結
這個springboot整合jwt只是一個很簡單的demo,并不是真正業務中使用方式。后面我會寫一個單點登錄的例子,會用到jwt。現在這里做一個入門練習。
總結
以上是生活随笔為你收集整理的spring boot jwt_springboot整合JWT的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab中asix off_matl
- 下一篇: latex textbf没有用_使用La