项目中使用到了jwt,用来在分布式项目中替代session;
jwt使用起来很简单,以下为我写的一个简单demo:
package rayeye.zq.com.tools; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Calendar; import java.util.Date; import java.util.Map; /** * Created by zq on 2017/3/18. */ public class JWT { private static Logger logger = LoggerFactory.getLogger(JWT.class); public static final String JWT_ISSUER_ALIAS = "TEST-TEST-Security"; public static final String JWT_SUBJECT = "user"; public static final String JWT_USER_ALIAS = "user"; public static final String JWT_VERSION = "3.0"; public static final String JWT_SECRET = "5EEDAAF1C9B4B5301B8537AB29C84308"; public JWT() { } // 获取加密后 的jwt字符串 public static String getJWTString(String sub, Date expires, Map<String, Object> claims) { JSONArray audience = new JSONArray(); if(claims == null) { throw new NullPointerException("NULL sub is claims"); } else { if(sub == null || "".equals(sub)) { sub = "user"; } if(expires == null) { throw new NullPointerException("NULL expires is illegal"); } else { if(claims.containsKey("roles")) { audience.add(claims.get("roles")); } SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; claims.put("exp", Long.valueOf(expires.getTime())); String jwtString = Jwts.builder().setIssuer("TEST-TEST-Security").setSubject(sub).setAudience(audience.toJSONString()).setClaims(claims).setExpiration(expires).setIssuedAt(new Date()).setId("3.0").signWith(signatureAlgorithm, "5EEDAAF1C9B4B5301B8537AB29C84308").compact(); return jwtString; } } } // 判断jwt是否有效 public static boolean isValid(String token) { try { Jwts.parser().setSigningKey("5EEDAAF1C9B4B5301B8537AB29C84308").parseClaimsJws(token.trim()); return true; } catch (Exception var2) { logger.error("Token check failure! Error:" + var2.getMessage()); return false; } } // 解析jwt public static String parseJWT(String jwsToken) { if(isValid(jwsToken)) { Claims claims = (Claims)Jwts.parser().setSigningKey("5EEDAAF1C9B4B5301B8537AB29C84308").parseClaimsJws(jwsToken).getBody(); return JSONObject.toJSONString(claims); } else { return null; } } // 设置jwt有效期 public static Date getExpiryDate(int minutes) { // 根据当前日期,来得到到期日期 Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.add(Calendar.MINUTE, minutes); return calendar.getTime(); } public static void main(String [] args){ Date expiry = getExpiryDate(7 * 24 * 60); JSONObject object = new JSONObject(); object.put("test1","test1"); object.put("test2","test2"); object.put("test2/","test2/"); String jwt = getJWTString("user",expiry,object); System.out.println(jwt); System.out.println("-------------------------------------------------------"); System.out.println(isValid(jwt)); System.out.println("-------------------------------------------------------"); System.out.print(parseJWT("eyJhbGciOiJIUzI1NiJ9.eyJ0ZXN0MiI6InRlc3QyIiwidGVzdDIvIjoidGVzdDIvIiwiZXhwIjoxNDkwNTMyNzc3LCJ0ZXN0MSI6InRlc3QxIiwiaWF0IjoxNDg5OTI3OTc3LCJqdGkiOiIzLjAifQ.NpMlrAaqi1MiWVVwHtIX2HihjE8HdBVgsWqaqev5YFk")); } }
相关maven:
<!-- jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.6.0</version>
</dependency>
//我暂时只是知道如何使用它,至于其底层原理则还没研究。后面会继续研究.
jwt的简单实现原理介绍:
jwt分为三部分:
1.header(头部)
{"typ": "JWT", "alg": "HS256"}
头部通常包含两部分,type:代表token的类型,这里使用的事JWT类型。alg:使用的Hash算法,例如HMAC SHA256或者RSA。
2.payload(负载)
{
"sub"
:
"1234567890"
,
"name"
:
"John Doe"
,
"admin"
:
true
}
负载包含了一些声明Claim。声明分三类:
1.)Reserved Claim,这是一套预定义的声明,并不是必须要是用的,例如:iss(issuer)、exp(expiration time)、sub(subject)、aud(audience)等
2.)public Claim,
3.)private Claim,交换信息的自定义声明.
3.signature 使用header中指定的算法讲编码后的header,编码后的payload,一个sercret进行加密,如下:
例如使用的是HMAC SHA256算法,大致流程类似于: HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
这个signature是用来验证信息是否被修改.
如此,可以保证jwt字符串可以用来实现信息认证的功能,
比如当遇到单点登录需求的时候,就可以考虑使用jwt来代替session,当然,也可以考虑redis代替session,这又是另一个话题,此处不谈.