CookieSession Redis 到JWT会话管理历史

单应用时期,通常使用 Cookies 和 Session 进行会话管理。

用户登录后,服务器创建一个唯一的会话标识符(Session ID),将其存储在浏览器的 Cookies

中,并在服务端维护一个关联该标识符的会话对象。

这种方式的问题在于,会话状态存储在服务器本地内存中,如果有多个应用实例,会导致会话状态

无法共享。

CookieSession Redis 到JWT会话管理历史_第1张图片

CookieSession Redis 到JWT会话管理历史_第2张图片

为了解决单应用的局限性,引入 Redis 作为分布式缓存存储会话数据。 

Redis 具有高性能、可伸缩性,而且可以集中管理分布式环境下的会话数据

简单点讲,就是多个应用连接同一个Redis实现会话共享

CookieSession Redis 到JWT会话管理历史_第3张图片

像SpringSession其实用的也是这套

其实原先的Token也是仿造了Session的机制,原理就是后端返回一个Token,然后每次请求是都将Token带到服务器,用Token作为Key来找对应的Value

JWT 是一种基于 Token 的认证机制,通过在客户端存储 Token,而不需要在服务器端保留会话状态。

可以说JWT是专门进行分布式会话管理的

在分布式系统中,不同服务之间可能需要共享用户会话信息。JWT 的结构允许信息被安全地编码为一个 Token,并在服务之间传递,而无需依赖共享的存储机制。

CookieSession Redis 到JWT会话管理历史_第4张图片

使用JWT

依赖



    io.jsonwebtoken
    jjwt-api


    io.jsonwebtoken
    jjwt-impl


    io.jsonwebtoken
    jjwt-jackson 


    junit
    junit
    test

 //创建JWT
    @Test
    public void testCreatedJwt() {
//        String s= UUID.randomUUID().toString().replace("-", "");
//        System.out.println("s="+s);
        //9f4224f2fb0d44cbbe5d03abd14a3bad
        String key = "9f4224f2fb0d44cbbe5d03abd14a3bad";//每个应用都需要用来解密的一个key 我这里用UUID生成
        //创建SeceretKey
        SecretKey secretKey = Keys.hmacShaKeyFor(key.getBytes(StandardCharsets.UTF_8));

        Map data = new HashMap<>();
        data.put("uid", 1001);
        data.put("name", "小王王");
        data.put("role", "经理");


        //DateUtils.addMinutes(new Date(), 10);用commons-lang3的工具类  指定时间上加多少分钟也可以
        //创建JWT 使用Jwts类
        String jwtToken = Jwts.builder().signWith(secretKey, SignatureAlgorithm.HS256) 设置签名密钥和使用的算法
                .setExpiration(new Date(new Date().getTime() + 60 * 10 * 1000))//设置过期时间10分钟之后
                .setIssuedAt(new Date())//设置令牌签发时间,即当前时间
                .setId(UUID.randomUUID().toString())// 设置JWT的唯一标识符(JTI)
                .addClaims(data)// 添加额外的声明(payload 中的数据)
                .compact();// 构建并压缩JWT成为一个字符串
        //eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDE0NjUyOTUsImlhdCI6MTcwMTQ2NDY5NSwianRpIjoiZDVmY2FlZmItYzJkMi00YzMxLWFhYzktYjcwNjZiYTUyNzViIiwicm9sZSI6Iue7j-eQhiIsIm5hbWUiOiLlsI_njovnjosiLCJpZCI6MTAwMX0.VLcmm-8dOjKVeobSwysXPZHvDkul-n3wLKAzSM7P4lw
        System.out.println(jwtToken);
    }

    //读JWT
    @Test
    public void readJwtTest() {
        String jwtToken = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDE0NzQwNjYsImlhdCI6MTcwMTQ3MzQ2NiwianRpIjoiMWU4OWM4YzktNGI2Yy00NmVmLWI1YWMtZDkyODEyODUxYTZmIiwidWlkIjoxMDAxLCJyb2xlIjoi57uP55CGIiwibmFtZSI6IuWwj-eOi-eOiyJ9.W1IfvHWHc-vbwM8tSwXUUFjFgZrr47qy8aC9rCedvUw";
        String key = "9f4224f2fb0d44cbbe5d03abd14a3bad";//每个应用都需要用来解密的一个key
        //创建SeceretKey
        SecretKey secretKey = Keys.hmacShaKeyFor(key.getBytes(StandardCharsets.UTF_8));

        //解析JWT 没有异常 继续读   有异常说明这个jwtToken是无效的  ExpiredJwtException过期异常
        Jws claimsJws = Jwts.parserBuilder()//创建一个JWT解析器的构建器对象,该对象用于配置JWT解析器的各种参数。
                .setSigningKey(secretKey)//设置JWT解析器使用的签名密钥,以便验证JWT的真实性
                .build()
                .parseClaimsJws(jwtToken);//使用构建好的JWT解析器解析JWT令牌。这个方法返回一个Jws对象,其中包含了JWT的各种声明(claims),以及相关的信息,如签名等。
        //读数据
        Claims body = claimsJws.getBody();
        //通过body可以获取所有原先放进去的值  举例
        Integer id = body.get("uid", Integer.class);
        System.out.println("uid=" + id);
        Object uid = body.get("uid");
        System.out.println("uid=" + uid);
        String name = (String) body.get("name");
        System.out.println("name=" + name);

        //JWT的唯一标识符
        String id3 = body.getId();
        System.out.println("唯一表示符:" + id3);
        //获取设置的过期时间
        Date expiration = body.getExpiration();
        System.out.println("过期时间:" + expiration);
    }

你可能感兴趣的:(java)