分布式session解决方案 — — JWT(生成token)

JWT 跨域认证解决方案

1 介绍

  • JWT(JSON Web Token)是目前最流行的跨域认证解决方案,是一种基于Token的认证授权机制,JWT本身也是Token,是一种规范化之后的JSON结构的Token。
  • JWT自身包含了验证所需要的所有信息,因此,我们的服务器不需要存储Session信息(其他解决方案:hash、session共享),增加了系统的可用性和伸缩性,大大减轻了服务端的压力。
  • JWT更符合RESTFul API的无状态原则
  • JWT认证可以有效避免CSRF(跨站请求伪造攻击),因为JWT一般是存在在localStorage中,使用JWT进行身份验证的过程中不会涉及到Cookie

2 组成部分

JWT本质就是一组字符串,通过(.)切分成三个为Base64编码的部分:

  1. Header:描述JWT元数据,定义生成签名的算法及Token类型
  2. Payload:存放实际要传递的数据
  3. Signature(签名):服务器通过Payload、Header和一个密钥(Secret)使用Header里面指定的签名算法(默认是HMAC SHA256)

实例:用点分割,分为三部分
在这里插入图片描述

3 JWT工具类的编写(企业开发)

3.1 定义对应编码及盐值(加密时)

//定义对应的编码算法
static SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
//盐值,盐值随意,看公司要求【此处我采用UUID】
static String secretKey = "d8de020f63754a9fa746ea74b831afc3";

3.2 获取key

//获取key(指定算法和盐值的key对象)
private static Key generateKey(){
    //将盐值转成字节
    byte[] bytes = DatatypeConverter.parseBase64Binary(secretKey);
    //根据算法和盐值生成对应的key值
    Key key = new SecretKeySpec(bytes, signatureAlgorithm.getJcaName());
    return key;
}

3.3 生成token(generatorToken)

/**
 * 将我们的数据使用JWT的方式变成一个token xxx.yyy.zzz
 * @param payLoad   负载(数据信息)
 * @return
 */
public static String generatorToken(Map<String, String> payLoad){
    ObjectMapper objectMapper = new ObjectMapper();
    try{
        //构建jwt生成器
        JwtBuilder builder = Jwts.builder();
        //将负载信息设置到jwt生成器中
        JwtBuilder jwtBuilder = builder.setPayload(objectMapper.writeValueAsString(payLoad));
        //根据签名算法和key值,生成新的jwtBuilder
        JwtBuilder jwtBuilder1 = jwtBuilder.signWith(signatureAlgorithm, generateKey());
        String token = jwtBuilder1.compact();
        return token;
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }
    return null;
}

3.4 获取token中的body信息

/**
  * 根据指定的token, 返回对应的body信息
  * @param token
  * @return
  */
 public static Claims phaseTokenGetBody(String token){
     JwtParser jwtParser = Jwts.parser().setSigningKey(generateKey());
     Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);
     Claims body = claimsJws.getBody();//主要存放的信息
     return body;
 }

3.5 获取token中的signature信息

/**
  * 根据指定的token获取签名信息
  * @param token
  * @return
  */
 public static String phaseTokenGetSignature(String token){
     JwtParser jwtParser = Jwts.parser().setSigningKey(generateKey());
     Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);
     String signature = claimsJws.getSignature();
     return signature;
 }

3.6 获取token中的头信息

/**
 * 根据指定的token获取头信息
 * @param token
 * @return
 */
public static JwsHeader phaseTokenGetHeader(String token){
    //获取解析器
    JwtParser parser = Jwts.parser();
    //设置签名key(盐值)
    parser = parser.setSigningKey(generateKey());
    //解析token
    Jws<Claims> claimsJws = parser.parseClaimsJws(token);
    JwsHeader header = claimsJws.getHeader();
    return header;
}

3.7 测试

①在map中存入自己的数据,调用自定义API生成对应token

public static void main(String[] args) {
    //随机获取盐值
//        System.out.println(UUID.randomUUID().toString().replaceAll("-", ""));
    Map<String, String> payLoad = new HashMap<>();
    payLoad.put("name", "curry");
    String s = generatorToken(payLoad);
    //eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiY3VycnkifQ.Sf3GiF3p56nLzoAxEHLXcAckPmmPTtecj1_lGT9oV8s
    System.out.println(s);
}

②在jwt官网https://jwt.io/中进行解析,也可以调用自己的API进行解析
在这里插入图片描述
调用自己API:

//调用自定义API获取结果
Claims claims = phaseTokenGetBody(s);
//{name=curry}

③如果所给token有误,则会报错

Exception in thread "main" io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.

4 全部代码包含测试

package com.zi.api.commons.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.*;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.HashMap;
import java.util.Map;

/**
 * 生成jwt工具类
 */
public class JJWTRootUtils {

    //定义对应的编码算法
    static SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
    //盐值
    static String secretKey = "d8de020f63754a9fa746ea74b831afc3";

    //获取key(指定算法和盐值的key对象)
    private static Key generateKey(){
        //将盐值转成字节
        byte[] bytes = DatatypeConverter.parseBase64Binary(secretKey);
        //根据算法和盐值生成对应的key值
        Key key = new SecretKeySpec(bytes, signatureAlgorithm.getJcaName());
        return key;
    }

    /**
     * 将我们的数据使用JWT的方式变成一个token xxx.yyy.zzz
     * @param payLoad   负载(数据信息)
     * @return
     */
    public static String generatorToken(Map<String, String> payLoad){
        ObjectMapper objectMapper = new ObjectMapper();
        try{
            //构建jwt生成器
            JwtBuilder builder = Jwts.builder();
            //将负载信息设置到jwt生成器中
            JwtBuilder jwtBuilder = builder.setPayload(objectMapper.writeValueAsString(payLoad));
            //根据签名算法和key值,生成新的jwtBuilder
            JwtBuilder jwtBuilder1 = jwtBuilder.signWith(signatureAlgorithm, generateKey());
            String token = jwtBuilder1.compact();
            return token;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据指定的token, 返回对应的body信息
     * @param token
     * @return
     */
    public static Claims phaseTokenGetBody(String token){
        JwtParser jwtParser = Jwts.parser().setSigningKey(generateKey());
        Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);
        Claims body = claimsJws.getBody();//主要存放的信息
        return body;
    }

    /**
     * 根据指定的token获取签名信息
     * @param token
     * @return
     */
    public static String phaseTokenGetSignature(String token){
        JwtParser jwtParser = Jwts.parser().setSigningKey(generateKey());
        Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);
        String signature = claimsJws.getSignature();
        return signature;
    }


    /**
     * 根据指定的token获取头信息
     * @param token
     * @return
     */
    public static JwsHeader phaseTokenGetHeader(String token){
        //获取解析器
        JwtParser parser = Jwts.parser();
        //设置签名key(盐值)
        parser = parser.setSigningKey(generateKey());
        //解析token
        Jws<Claims> claimsJws = parser.parseClaimsJws(token);
        JwsHeader header = claimsJws.getHeader();
        return header;
    }


    public static void main(String[] args) {
        //随机获取盐值
//        System.out.println(UUID.randomUUID().toString().replaceAll("-", ""));
        Map<String, String> payLoad = new HashMap<>();
        payLoad.put("name", "curry");
        String s = generatorToken(payLoad);
        //eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiY3VycnkifQ.Sf3GiF3p56nLzoAxEHLXcAckPmmPTtecj1_lGT9oV8s
        System.out.println(s);

        //调用自定义API获取结果
        Claims claims = phaseTokenGetBody(s);
        //{name=curry}
        System.out.println(claims);
    }

}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Session、Cookie、TokenJWT都是在Web开发中用于管理用户身份认证和会话管理的工具。 1. SessionSession指的是服务器端保存的用户信息。当用户登录成功后,服务器会创建一个session,为该用户分配一个session ID,并将该ID保存到cookie中,发送给客户端。客户端浏览器保存了这个cookie,以后每次请求都会带上这个cookie,服务器通过这个cookie就可以识别出用户身份,从而进行相应的操作。Session机制存在一定的风险,比如会话劫持、会话固定等问题,需要注意安全性。 2. Cookie:Cookie是一种客户端保存用户信息的机制,它是由服务器在响应HTTP请求时通过Set-Cookie头部字段发给客户端浏览器的一小段文本信息。浏览器将这些信息保存在客户端,以后每次向服务器发送请求时都会自动带上这些cookie,从而实现身份认证和会话管理。但是Cookie也存在一些安全问题,比如会话劫持、跨站脚本攻击等问题。 3. TokenToken是一种用户身份认证和授权的机制,通常由服务器生成,以便在客户端和服务端之间进行身份认证和授权。客户端在登录成功后,服务器会为该用户生成一个Token,并将Token发送给客户端浏览器。客户端在之后的请求中需要携带该Token,服务器验证Token的有效性后,就可以识别出用户身份,并进行相应的操作。Token相比Session和Cookie,具有更高的安全性和可扩展性。 4. JWTJWT是一种基于Token的身份认证和授权机制。JWT包含三部分,分别是头部、载荷和签名。头部包含加密算法和类型等信息;载荷包含用户的身份信息和相关的元数据等信息;签名则是对头部和载荷进行签名生成的一段密文,用于验证Token的有效性。JWT具有无状态、可扩展、跨域等特点,被广泛用于Web开发中的用户身份认证和授权。 ### 回答2: Session、Cookie、TokenJWT都是常见的身份验证和会话管理方法。下面我会分别介绍它们。 SessionSession是服务器端记录用户状态的一种机制。当用户通过用户名和密码登录后,服务器会为该用户创建一个唯一的Session。之后,用户再发送请求时,服务器会根据Session来识别用户并获取用户的状态信息。 Cookie:Cookie是一种在客户端存储的小型文本文件。在用户通过用户名和密码登录成功后,服务器可以将一个包含Session信息的Cookie发送给客户端,客户端会将该Cookie保存下来。之后,客户端发送请求时,会自动附带上该Cookie,用于向服务器证明用户的身份。 TokenToken是一种代表用户身份的令牌。与Cookie不同,Token是在客户端保存的,并且不需要服务器端存储用户状态。当用户登录成功后,服务器会生成一个Token并发送给客户端,客户端将其保存起来。之后,客户端发送请求时,会将Token作为请求头信息的一部分发送给服务器,服务器根据Token验证用户身份。 JWTJWT(JSON Web Token)是一种基于JSON的开放标准,用于在各方之间安全传输信息。它由三部分组成:Header、Payload和Signature。其中,Header用于描述JWT的元数据,Payload用于存储实际传输的数据,Signature用于验证JWT的合法性。在使用JWT进行身份验证时,服务器会生成一个JWT并发送给客户端,客户端将其保存起来。之后,客户端发送请求时,会将JWT作为请求头信息的一部分发送给服务器,服务器根据JWT验证用户身份的合法性。 总结:Session、Cookie、TokenJWT都是常用于身份验证和会话管理的方法,它们各有优劣和适用场景。Session和Cookie依赖于服务器端存储用户状态,而TokenJWT则可以减轻服务器的负担,并且适用于分布式系统。其中,JWT由于其自包含性和可扩展性,在分布式系统和前后端分离的架构中得到了广泛应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值