1、单机tomcat应用时代的登录检验
sesssion保存在浏览器和应用服务器会话之间
用户登录成功,服务端会保证一个session,会给客户端一个sessionId
客户端访问的时候会把sessionId保存在cookie中,每次请求都会携带这个sessionId
2、分布式应用中的session共享
真实的应用不可能单节点部署,所以就有个多节点登录session共享的问题需要解决
1)tomcat支持session共享,但是有广播风暴;用户量大的时候,占用资源就严重,不推荐
2)使用redis存储token:服务端使用UUID生成随机64位或者128位token,放入redis中,然后返回给客户端并存储在cookie中,用户每次访问都携带此token,服务端去redis中校验是否有此用户即可,这种方式目前也有很多公司都在使用。但是这种方式不是最优的方案,这种方式需要每次都去redis里拿数据检验一下,在访问量大的时候,每次访问redis也是一种资源(比如网络资源和IO)的消耗,所以现在很多应用已经开始使用我们今天要讲的JWT
1、JWT是一个开放标准,它定义了一种用于简洁,自包含的,用于通信双方之间以 JSON 对象的形式安全传递信息的方法。
JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名
简单来说,就是通过一定规范来生成token,然后可以通过解密算法逆向解密token,这样就可以获取用户信息
优点:
1)生产的token可以包含基本信息,比如id、用户昵称、头像等信息,避免再次查库
2)存储在客户端,不占用服务端的内存资源
缺点:token是经过base64编码,所以可以解码,因此token加密前的对象不应该包含敏感信息,如用户权限,密码等
2、JWT格式组成 头部、负载、签名
header+payload+signature
头部:主要是描述签名算法
负载:主要描述是加密对象的信息,如用户的id等,也可以加些规范里面的东西,如iss签发者,exp 过期时间,sub 面向的用户
签名:主要是把前面两部分进行加密,防止别人拿到token进行base解密后篡改token
3、关于jwt客户端存储
可以存储在cookie,localstorage和sessionStorage里面
1、加入相关依赖
io.jsonwebtoken
jjwt
0.7.0
2、开发加密生成JWT的token方法和解密检验token方法
package com.cj.wx_pay.utils;
import com.cj.wx_pay.domain.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
/**
* jwt工具类
*/
public class JwtUtils {
public static final String SUBJECT = "wx_pay";
public static final long EXPIRE = 1000*60*60*24*7; //过期时间,毫秒,一周
//秘钥
public static final String APPSECRET = "wx_pay666";
/**
* 生成jwt
* @param user
* @return
*/
public static String geneJsonWebToken(User user){
if(user == null || user.getId() == null || user.getName() == null
|| user.getHeadImg()==null){
return null;
}
String token = Jwts.builder().setSubject(SUBJECT) //对应头部
.claim("id",user.getId())
.claim("name",user.getName())
.claim("img",user.getHeadImg()) //对应负载,就是根据需求往加密串里加的用户信息
.setIssuedAt(new Date()) //发行时间
.setExpiration(new Date(System.currentTimeMillis()+EXPIRE)) //有效期
.signWith(SignatureAlgorithm.HS256,APPSECRET).compact();//对应签名,主要是把前面两部分进行加密
return token;
}
/**
* 解密校验token
* @param token
* @return
*/
public static Claims checkJWT(String token ){
try{
final Claims claims = Jwts.parser().setSigningKey(APPSECRET).parseClaimsJws(token).getBody();
return claims;
}catch (Exception e){ }
return null;
}
}
3、测试验证
@GetMapping("testGeneJwt")
public JsonData testGeneJwt(){
User user = new User();
user.setId(666);
user.setHeadImg("www.baidu.com/1.jpg");
user.setName("zhangsan");
String token = JwtUtils.geneJsonWebToken(user);
return JsonData.buildSuccess(token);
}
@GetMapping("testCheck")
public JsonData testCheck(@RequestParam("token") String token){
Claims claims = JwtUtils.checkJWT(token);
if(claims != null){
String name = (String)claims.get("name");
String img = (String)claims.get("img");
int id =(Integer) claims.get("id");
User user = new User();
user.setId(id);
user.setHeadImg(img);
user.setName(name);
return JsonData.buildSuccess(user);
}else{
return JsonData.buildError("非法token");
}
}
看下加密返回的结果
把加密的token作为参数传进去,看下解密的结果
可以看到已经解密成功了,我们再随便拿一个不是我们JWT生成的token串儿试一下,看是否能解密成功
可以看到随便伪造的token提示非法token
以上就是对JWT的一些基本使用方法,有需要或者感兴趣的小伙伴可以试一下