spring boot jwt_springboot整合JWT
springboot整合JWT
一、JWT介紹
JSON Web token簡稱JWT, 是用于對應(yīng)用程序上的用戶進(jìn)行身份驗(yàn)證的標(biāo)記。也就是說, 使用 JWTS 的應(yīng)用程序不再需要保存有關(guān)其用戶的 cookie 或其他session數(shù)據(jù)。此特性便于可伸縮性, 同時(shí)保證應(yīng)用程序的安全。
在身份驗(yàn)證過程中, 當(dāng)用戶使用其憑據(jù)成功登錄時(shí), 將返回 JSON Web token, 并且必須在本地保存 (通常在本地存儲(chǔ)中)。每當(dāng)用戶要訪問受保護(hù)的路由或資源 (端點(diǎn)) 時(shí), 用戶代理(user agent)必須連同請求一起發(fā)送 JWT, 通常在授權(quán)標(biāo)頭中使用Bearer schema。后端服務(wù)器接收到帶有 JWT 的請求時(shí), 首先要做的是驗(yàn)證token。
1.JWT的格式
JWT就是一個(gè)字符串,經(jīng)過加密處理與校驗(yàn)處理的字符串,形式為:A.B.C,第一部分我們稱它為頭部(header),第二部分我們稱其為載荷(payload, 類似于飛機(jī)上承載的物品),第三部分是簽證(signature).
A由JWT頭部信息header加密得到
B由JWT用到的身份驗(yàn)證信息json數(shù)據(jù)加密得到
C由A和B加密得到,是校驗(yàn)部分
2.怎樣使用token?
可以放到HTTP請求的請求頭中,通常是Authorization字段。
3.流程圖
二、java代碼實(shí)現(xiàn)
springboot經(jīng)典的四個(gè)步驟1.改pom2.寫yml/properties3.啟動(dòng)類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
沒用這個(gè)里面的
server.port=8087 # 要加密的明文 jwt.secret=hand2020 # tocken 過期時(shí)間,單位秒 jwt.expire=3003.啟動(dòng)類
這里選擇使用@ServletComponentScan,是因?yàn)樵贔ilter類用@component和@configuration會(huì)導(dǎo)致
@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掃描加載進(jìn)spring容器 public class BootJwtApplication {public static void main(String[] args) {SpringApplication.run(BootJwtApplication.class, args);}}4.實(shí)現(xiàn)代碼
這里主要是做一個(gè)簡單的demo驗(yàn)證,有三個(gè)類JwtController、CreatToken、JwtFilter。
JwtController:用來接收rest請求。
JwtUtil:用來生成token,解密token,驗(yàn)證token
JwtFilter:用來攔截請求對http請求中攜帶的token進(jìn)行驗(yàn)證
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
這里我是在配置文件中讀需要加密的明文,和過期時(shí)間。也可以在controller里處理參數(shù)設(shè)置。
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過期時(shí)間* @param user 登錄成功的user對象* @return*/public static String createJWT(long ttlMillis, User user) {//指定簽名的時(shí)候使用的簽名算法,也就是header那部分,jjwt已經(jīng)將這部分內(nèi)容封裝好了。SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;//生成JWT的時(shí)間long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis);//創(chuàng)建payload的私有聲明(根據(jù)特定的業(yè)務(wù)需要添加,如果要拿這個(gè)做驗(yàn)證,一般是需要和jwt的接收方提前溝通好驗(yàn)證方式的)Map<String, Object> claims = new HashMap<String, Object>();claims.put("id", user.getId());claims.put("username", user.getUsername());claims.put("password", user.getPassword());//生成簽名的時(shí)候使用的秘鑰secret,這個(gè)方法本地封裝了的,一般可以從本地配置文件中讀取,切記這個(gè)秘鑰不能外露哦。它就是你服務(wù)端的私鑰,在任何場景都不應(yīng)該流露出去。一旦客戶端得知這個(gè)secret, 那就意味著客戶端是可以自我簽發(fā)jwt了。String key = user.getPassword();//生成簽發(fā)人String subject = user.getUsername();//下面就是在為payload添加各種標(biāo)準(zhǔn)聲明和私有聲明了//這里其實(shí)就是new一個(gè)JwtBuilder,設(shè)置jwt的bodyJwtBuilder builder = Jwts.builder()//如果有私有聲明,一定要先設(shè)置這個(gè)自己創(chuàng)建的私有的聲明,這個(gè)是給builder的claim賦值,一旦寫在標(biāo)準(zhǔn)的聲明賦值之后,就是覆蓋了那些標(biāo)準(zhǔn)的聲明的.setClaims(claims)//設(shè)置jti(JWT ID):是JWT的唯一標(biāo)識(shí),根據(jù)業(yè)務(wù)需要,這個(gè)可以設(shè)置為一個(gè)不重復(fù)的值,主要用來作為一次性token,從而回避重放攻擊。.setId(UUID.randomUUID().toString())//iat: jwt的簽發(fā)時(shí)間.setIssuedAt(now)//代表這個(gè)JWT的主體,即它的所有人,這個(gè)是一個(gè)json格式的字符串,可以存放什么userid,roldid之類的,作為什么用戶的唯一標(biāo)志。.setSubject(subject)//設(shè)置簽名使用的簽名算法和簽名使用的秘鑰.signWith(signatureAlgorithm, key);if (ttlMillis >= 0) {long expMillis = nowMillis + ttlMillis;Date exp = new Date(expMillis);//設(shè)置過期時(shí)間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()//設(shè)置簽名的秘鑰.setSigningKey(key)//設(shè)置需要解析的jwt.parseClaimsJws(token).getBody();return claims;}/*** 校驗(yàn)token* 在這里可以使用官方的校驗(yàn),我這里校驗(yàn)的是token中攜帶的密碼于數(shù)據(jù)庫一致的話就校驗(yàn)通過* @param token* @param user* @return*/public static Boolean isVerify(String token, User user) {//簽名秘鑰,和生成的簽名的秘鑰一模一樣String key = user.getPassword();//Jwts.parser在執(zhí)行parseClaimsJws(token)時(shí)如果token時(shí)間過期會(huì)拋出ExpiredJwtException異常try {//得到DefaultJwtParserClaims claims = Jwts.parser()//設(shè)置簽名的秘鑰.setSigningKey(key)//設(shè)置需要解析的jwt.parseClaimsJws(token).getBody();if (claims.get("password").equals(user.getPassword())) {return true;}}catch (ExpiredJwtException e){e.printStackTrace();}return false;}}JwtFilter
過濾器是通過實(shí)現(xiàn)Filter接口,注意@WebFilter相當(dāng)于xml配置,但是需要在啟動(dòng)類上注解
@ServletComponentScan,將JwtFilter加入到spring容器中。
在JwtFilter類上注解@component或@configuration會(huì)導(dǎo)致@WebFilter失效從而攔截所有請求
目前這個(gè)沒用到,直接在controller里做了判斷,這個(gè)是后續(xù)業(yè)務(wù)需求的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.瀏覽器發(fā)送請求獲取token
http://localhost:8087/get
2.將token放入請求頭中請求
注意將上次請求獲得的token放入請求頭內(nèi)(注意不要過太長時(shí)間因?yàn)閠oken設(shè)置了40秒過期)http://localhost:8087/test
token超時(shí):
總結(jié)
這個(gè)springboot整合jwt只是一個(gè)很簡單的demo,并不是真正業(yè)務(wù)中使用方式。后面我會(huì)寫一個(gè)單點(diǎn)登錄的例子,會(huì)用到j(luò)wt。現(xiàn)在這里做一個(gè)入門練習(xí)。
總結(jié)
以上是生活随笔為你收集整理的spring boot jwt_springboot整合JWT的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab中asix off_matl
- 下一篇: latex textbf没有用_使用La