JWT的生成及驗證過程
阿新 • • 發佈:2019-02-19
在前後端分離的場景中,前後臺主要用jwt互動,比如說前端發一個提交資訊的請求,後臺必須知道這個提交者的資訊吧(提交者id),但為了使傳輸更安全,jwt包含了需要的使用者資訊以加密的方式傳輸以達到這個目的。
先看看jwt的定義,網上隨處可見的:jwt全稱Json Web Token,由三部分構成:頭部(header)、載荷(payload, )、簽證(signature).
傳輸資訊用到的就是載荷:就是存放有效資訊的地方,就是這樣的鍵值對構成的Map物件:
jwt用Claims物件來存自定義的資訊(也是一個鍵值對的Map物件):當登入的時候,就把當前的使用者的資訊存進去,這裡模擬一下(假如從資料庫中獲取了使用者資訊)iss: jwt簽發者 sub: jwt所面向的使用者 aud: 接收jwt的一方 exp: jwt的過期時間,這個過期時間必須要大於簽發時間 nbf: 定義在什麼時間之前,該jwt都是不可用的. iat: jwt的簽發時間 jti: jwt的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊。
然後把資訊存到一個map裡面,通過工具生成token字串返回給前臺,當前臺再次請求的時候就帶上這個token,然後取引數驗證。@ResponseBody @RequestMapping("login.do") public JsonAndModel sayHello(HttpServletRequest request, HttpServletResponse response) { Map<String,Object> claims = new HashMap<>(); claims.put("username","wang"); claims.put("userid",12); System.out.println(new Date().getTime() + "---start---"); return JsonAndModel.builder(TokenUtil.tokens(claims)).build(); }
驗證過程:把前端存到header裡面的token解析成一個Claims物件獲取引數驗證(當時間過了設定的token失效時間,這個物件就失效為null,也就未登入)package cn.wzy.util; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import java.util.*; /** * @author wzy * @Date 2018/4/6 14:00 */ public class TokenUtil { private static Properties properties = new Properties(); private static ResourceBundle resource = ResourceBundle.getBundle("database"); public static Object getValue(String key) { return resource.getString(key); } public static String tokens(Map<String,Object> claims) { String SecretKey = (String) getValue("secretkey"); //獲取當前的時間 Calendar calendar = Calendar.getInstance(); Date date = new Date(System.currentTimeMillis()); calendar.setTime(date); //向後退後的秒數 int time = Integer.parseInt((String) getValue("millisecond")); calendar.add(Calendar.MILLISECOND, time); Date endTime = calendar.getTime(); String issuer = (String) getValue("JWT_ISSUER"); String aud = (String) getValue("JWT_AUD"); JwtBuilder builder = Jwts.builder().setClaims(claims) .signWith(SignatureAlgorithm.HS256,SecretKey) .setClaims(claims) .setSubject((String)claims.get("username")) .setIssuedAt(new Date()) .setExpiration(endTime) .setIssuer(issuer) .setAudience(aud); return builder.compact(); } /** * 從jwt中獲取使用者資訊 * @param jsonWebToken * @return */ public static Claims parseJWT(String jsonWebToken) { String secretKey = (String) getValue("secretkey"); try { Claims claims = Jwts.parser() .setSigningKey(secretKey) .parseClaimsJws(jsonWebToken).getBody(); return claims; } catch (Exception ex) { return null; } } }
@ResponseBody
@RequestMapping("checkOnlie.do")
public JsonAndModel check(HttpServletRequest request, HttpServletResponse response) {
String claims = request.getHeader("claims");
Claims info = null;
if (claims != null) {
info = TokenUtil.parseJWT(claims);
System.out.println(info == null);
System.out.println(new Date().getTime());
}
return JsonAndModel.builder(info).build();
}