创建javaweb项目并引入jwt的maven依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
编写JWT工具类
public class JwtUtil {
private static final String secret = "you can't tell anyone!";
/**
* 生产JWT
* @return
*/
public static String createJwt(){
//加密算法
SignatureAlgorithm alm = SignatureAlgorithm.HS256;
Map<String,Object> claims = new HashMap<>();
/** 有效载荷 **/
//jwt的签发时间
claims.put("iat",System.currentTimeMillis());
//jwt的过期时间,这个过期时间必须要大于签发时间
claims.put("exp",System.currentTimeMillis()+2);
//用户ID
claims.put("userId","001");
//用户名
claims.put("userName","lisa");
//构建JWT
JwtBuilder builder = Jwts.builder().addClaims(claims).signWith(alm, secret);
return builder.compact();
}
/**
* 校验JWT
* @param jwt
* @return
*/
public static boolean check(String jwt){
try {
JwtParser parser = Jwts.parser().setSigningKey(secret);
Jwt jwtObj = parser.parseClaimsJws(jwt);
Claims claims = (Claims)jwtObj.getBody();
//获取并校验失效时间
long exp = (Long) claims.get("exp");
if(System.currentTimeMillis() > exp){
System.out.print("token过期啦!!!");
return false;
}
}catch (Exception e){
e.printStackTrace();
return false;
}
return true;
}
public static void main(String[] args) {
//生成JWT
String jwtstr = createJwt();
//校验JWT
check(jwtstr);
}
}
额。。。。就酱。。。。。。太简单了吧🙄
是不是一下子就觉得什么session,cookie都可以丢掉了,单点登录啥的都是小case了。(我刚刚开始的时候就是这么想的。。。)
JWT的局限性
but,其实JWT还挺有局限性的,查阅了很多大神的文章总结如下:
参考:
1、https://cloud.tencent.com/developer/article/1495531
2、https://mp.weixin.qq.com/s?__biz=MzI0NzEyODIyOA==&mid=2247483918&idx=1&sn=12683bae55f2ab1a8281ab398472362f&chksm=e9b58bc5dec202d385d1c1d861f7e0ff495296ed9387b32a8d01ae195eae03688e5aeebe6396&mpshare=1&scene=23&srcid=0505snLrWQ4JjwVW94oSMJaK#rd](https://mp.weixin.qq.com/s?__biz=MzI0NzEyODIyOA==&mid=2247483918&idx=1&sn=12683bae55f2ab1a8281ab398472362f&chksm=e9b58bc5dec202d385d1c1d861f7e0ff495296ed9387b32a8d01ae195eae03688e5aeebe6396&mpshare=1&scene=23&srcid=0505snLrWQ4JjwVW94oSMJaK#rd
1、严重依赖于秘钥
JWT能保证其信息不可篡改的秘密就是因为你设置了一个别人不知道的密钥,但是这个秘钥要是被别人知道了,别人就可以根据头部指定的加密算法和秘钥随意篡改生成新的JWT.
2、有被破解的风险
因为JWT的无状态性,如果别人拿到了你的jwt,就算已经过期,他依旧可能通过暴力破解的方式去破解并拿到你的秘钥,因为加密算法是知道的,header和载荷也只是base64.encode了一下,相当于明文,就差个秘钥了,试一试说不定就被试出来了。而对这件事你无能为力的,因为整个破解过程不需要请求服务器,你压根不知道人家破解你的秘钥。
- 解决方案
避免jwt泄露(使用 https 加密应用,返回 jwt 给客户端时设置 httpOnly=true ,使用 cookie 而不是 LocalStorage 存储 jwt,这样可以防止 XSS 攻击和 CSRF 攻击);秘钥设置超过30位,并定期更新秘钥。
3、服务端无法管理客户端的信息
如果用户身份发生异常(信息泄露,或者被攻击),服务端很难向操作 Session 那样主动将异常用户进行隔离;已经签发的有效期内的JWT,就算用户注销了它还是有效的额
- 解决方案:把secret设置成用户相关的,比如userId_*****,这样,一旦发现用户异常,及时修改用户秘钥导致jwt校验失败
4、服务端无法主动推送消息
服务端由于是无状态的,他将无法使用像 Session 那样的方式推送消息到客户端,例如过期时间将至,服务端无法主动为用户续约,需要客户端向服务端发起续约请求
- 解决方案:你可以在临近过期时间时主动更新一下JWT再返回给客服端
5、冗余的数据开销
一个JWT签名的大小要远比一个 Session ID 长很多,如果你对有效载荷(payload)中的数据不做有效控制,其长度会成几何倍数增长,且在每一次请求时都需要负担额外的网络开销。
总结
JWT简单易用,但是因为也正是因为他的简单易用有很多问题,需要根据自己的项目场景好好考虑,目前我主要用来做 restful api 的身份认证,目前还好,等我进坑了再来写血书😊。
网友评论