组成
java web token简称jwt
应用环境
二次登录,即第一次登录后,关闭页面,一段时间内重新访问不需要重新登录
原实现方式:由服务器存储登录信息,当第二次请求过来时判断以前是否登录过,若是则直接访问
- 客户端请求
- 服务器产生登录信息
- 登录信息传给客户端,客户端存储在cookie中
- 客户端第二次访问时带cookie请求
- 服务器端进行校验
注:弊端,由于登录信息存在session中,即存在内存中会占用服务器资源
现解决办法:第一次登录请求,服务器产生token,存储客户端,第二次访问校验token
- 客户端请求
- 服务端产生token
- 客户端存储token
- 客户端第二次访问时带token
- 服务器进行校验
解决疑问
token的头部和有效载荷通过base64加密安全吗?
答:正因为如此,不能在有效载荷中放入涉及安全的信息如密码
有效载荷被篡改了怎么办?
答:由服务器产生,由服务器校验,即使token在第二次请求的时候被拦截,然后对里面的有效载荷进行篡改,在进行校验的时候,会比对签名串信息,若将头部和有效载荷以及密钥进行加密后与签名串不能匹配则表示被篡改
代码实现
1 2 3 4 5
| <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.18.2</version> </dependency>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| private static String SecretKey = "5oiR5piv5aSn5biF5ZOl";
public static void main(String[] args) { String token = creatToken(); analysisToken(token); }
public static String creatToken(){ Map<String, Object> map = new HashMap<>(); map.put("alg", "HS256"); map.put("typ", "JWT");
LocalDateTime nowLocalDateTime = LocalDateTime.now(); Date nowDate = Date.from(nowLocalDateTime.atZone(ZoneId.systemDefault()).toInstant()); LocalDateTime expireLocalDateTime = nowLocalDateTime.plusMinutes(30); Date expireDate = Date.from(expireLocalDateTime.atZone(ZoneId.systemDefault()).toInstant());
String token = JWT.create() .withHeader(map) .withSubject("test") .withClaim("username","wp") .withClaim("account","13245678912") .withIssuedAt(nowDate) .withExpiresAt(expireDate) .sign(Algorithm.HMAC256(SecretKey));
System.out.println(token); return token; }
public static void analysisToken(String token){ JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SecretKey)).build(); try { DecodedJWT jwt = verifier.verify(token); } catch (SignatureVerificationException e) { e.printStackTrace(); System.out.println("签名校验失败"); }
DecodedJWT decodedJWT = JWT.decode(token); Map<String, Claim> map = decodedJWT.getClaims(); Iterator<Map.Entry<String,Claim>> it=map.entrySet().iterator(); while(it.hasNext()){ Map.Entry<String,Claim> entry=it.next(); System.out.println("key:"+entry.getKey()+" " +"Value:"+entry.getValue()); } }
|