目录
1、为什么使用JWT?
2、JWT 的 格式
3、使用 JWT 就绝对安全 吗?
4、JWT 的 鉴权 流程
5、JWT 入门案例
5.1 引入依赖
5.2 生成Token
5.3 解析Token
5.4 工具类
JSON Web token简称JWT, 是用于对应用程序上的用户进行身份验证的标记。
也就是说, 使用 JWTS 的应用程序不再需要保存有关其用户的 cookie 或其他session数据。
此特性便于可伸缩性, 同时保证应用程序的安全
在不使用JWT的情况下,我们一般选择的是cookie和session来进行服务鉴权(判断是否登录,是否具有某种权限),但是这是针对于只有一个客户端的情况下,现在客户端从pc端增长到了app端,现在就是多端访问了。
在多端访问的情况下,可能就会存在一个问题,获取不到session和cookie。
同时在我们的服务端,通过集群的形式来进行搭建 ,也就是说服务端有多个共同提供服务,如果第一个服务器里记录session,那第二个服务如何获取呢?这些都是现实存在的问题, 那我们该如何解决?
这就引出了在微服务架构中如何进行服务鉴权的方案,这个方案就是 JWT.
JWT就是一个字符串,经过加密处理与校验处理的字符串,形式为:A.B.C 三段,每一段中间通过 . 来隔开
如果你还感觉不到清晰,这里有它的官方网站 : JSON Web Tokens - jwt.io
进入官方网站往下拉。
答案:
不安全
虽然我们看到JWT 经过多层加密。但是我们随便在网上找一个jwt 的 反解码工具,将JWT 处理后的字符串放进去。
大家可以发现,数据原封不动的还原了,所以在这里提醒大家对于敏感数据,比如用户的密码,账户的金额登录信息不应该存到JWT 字符串中,因为可以被解密。
JWT 如何判断是否登录呢?如何获取用户的用户信息呢?
这些内容就是JWT 的鉴权功能。
接下来我们来了解一下JWT 的 是如何鉴权的。
首先是登陆,客户端登陆的时候将用户的信息,用户名+密码发送到服务端。
服务端判断完之后,通过用户信息生成 JWT Token。
接着将生成的Token 响应给客户端,客户端再记录到本地。
这个时候客户端有一个Toke 字符串里面有了用户信息,那么接下来客户端去访问其他接口,将Token,写入到请求头当中,发送到服务端,服务端就可以通过token来获取信息。
这里还要对Token 进行校验,看他是否是我们生成的,是否被进行了数据篡改。
如果全部没有问题,完成业务逻辑,最终响应给客户端。
当然啦,如果Token 有问题,就要响应给客户端,您未登录或者鉴权为通过。
这就是JWT 的鉴权流程了。
接下来就带大家如何在JAVA 中使用JWT。
io.jsonwebtoken jjwt-api 0.11.2
public void testCreateToken() {//生成token//1、准备数据Map map = new HashMap();map.put("id",1);map.put("mobile","110");//2、使用JWT的工具类生成tokenlong now = System.currentTimeMillis();String token = Jwts.builder().signWith(SignatureAlgorithm.HS512, "yiqie") //指定加密算法.setClaims(map) //写入数据.setExpiration(new Date(now + 30000)) //失效时间.compact();System.out.println(token);
}
执行效果:
public void testParseToken() {String token = "eyJhbGciOiJIUzUxMiJ9.eyJtb2JpbGUiOiIxMTAiLCJpZCI6MSwiZXhwIjoxNjY1MTI1MTkyfQ.0VU2gdRpJ1eEoDFev740VkVKrdT_bYecgB3qcw-ZtrhZstFbAFwhAhESXaHb-11AxG3AjZKEEWVoaBlkzFd6ug";try {Claims claims = Jwts.parser().setSigningKey("yiqie").parseClaimsJws(token).getBody();Object id = claims.get("id");Object mobile = claims.get("mobile");System.out.println(id + "--" + mobile);}catch (ExpiredJwtException e) {System.out.println("token已过期");}catch (SignatureException e) {System.out.println("token不合法");}
}
对于JWT 的生成和解析,我们可以整合成一个工具类,便于我们自己后续使用。
public class JwtUtils {// TOKEN的有效期1小时(S)private static final int TOKEN_TIME_OUT = 1 * 3600;// 加密KEYprivate static final String TOKEN_SECRET = "yiqie";// 生成Tokenpublic static String getToken(Map params){long currentTime = System.currentTimeMillis();return Jwts.builder().signWith(SignatureAlgorithm.HS512, TOKEN_SECRET) //加密方式.setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000)) //过期时间戳.addClaims(params).compact();}/*** 获取Token中的claims信息*/public static Claims getClaims(String token) {return Jwts.parser().setSigningKey(TOKEN_SECRET).parseClaimsJws(token).getBody();}/*** 是否有效 true-有效,false-失效*/public static boolean verifyToken(String token) {if(StringUtils.isEmpty(token)) {return false;}try {Claims claims = Jwts.parser().setSigningKey("yiqie").parseClaimsJws(token).getBody();}catch (Exception e) {return false;}return true;}
}