利用JWT生成Token

作者: 蓝汝丶琪 | 来源:发表于2018-03-26 22:30 被阅读250次

    开篇

    实现Token的方式有很多,本篇介绍的是利用Json Web Token(JWT)生成的Token.JWT生成的Token有什么好处呢?

    • 安全性比较高,加上密匙加密而且支持多种算法。
    • 携带的信息是自定义的,而且可以做到验证token是否过期。
    • 验证信息可以由前端保存,后端不需要为保存token消耗内存。

    本篇分3部分进行讲解。

      1. 什么是JWT
      1. JWT的代码实现,代码将JWT封装成两个工具类,可以直接调用。
      1. 总结

    如果原理很难懂,没关系。可以直接看JWT的代码实现。代码已经上传github。已经对代码进行封装成工具类。可以直接使用。

    什么是JWT

    JSON Web Token 简称JWT。
    一个JWT实际上就是一个字符串,它由三部分组成,头部载荷签名
    JWT生成的token是这样的

    eyJpc3MiOiJKb2huI.eyJpc3MiOiJ.Kb2huIFd1IEp
    

    生成的token,是3段,用.连接。下面有解释。

    头部

    用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以被表示成一个JSON对象。
    例如:

    {
       "typ": "JWT",
      "alg": "HS256"
    }
    

    载荷

    其实就是自定义的数据,一般存储用户Id,过期时间等信息。也就是JWT的核心所在,因为这些数据就是使后端知道此token是哪个用户已经登录的凭证。而且这些数据是存在token里面的,由前端携带,所以后端几乎不需要保存任何数据。
    例如:

    {
      "uid": "xxxxidid",  //用户id
      "exp": "12121212"  //过期时间
    }
    

    签名

    签名其实就是:
    1.头部和载荷各自base64加密后用.连接起来,然后就形成了xxx.xx的前两段token。
    2.最后一段token的形成是,前两段加入一个密匙用HS256算法或者其他算法加密形成。

    1. 所以token3段的形成就是在签名处形成的。

    JWT的原理参考文章

    代码实现

    1.看代码前一定要知道JWT是由头部载荷签名组成。
    2.代码已上传github,希望点个赞

    1. 代码将JWT封装成两个工具类,可以直接调用。

    需要下载的jar包

    <dependency>
                <groupId>com.nimbusds</groupId>
                <artifactId>nimbus-jose-jwt</artifactId>
                <version>4.23</version>
    </dependency>
    

    生成token

     /**
         * 1.创建一个32-byte的密匙
         */
    
        private static final byte[] secret = "geiwodiangasfdjsikolkjikolkijswe".getBytes();
    
    
        //生成一个token
        public static String creatToken(Map<String,Object> payloadMap) throws JOSEException {
    
            //3.先建立一个头部Header
            /**
             * JWSHeader参数:1.加密算法法则,2.类型,3.。。。。。。。
             * 一般只需要传入加密算法法则就可以。
             * 这里则采用HS256
             *
             * JWSAlgorithm类里面有所有的加密算法法则,直接调用。
             */
            JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.HS256);
    
            //建立一个载荷Payload
            Payload payload = new Payload(new JSONObject(payloadMap));
    
            //将头部和载荷结合在一起
            JWSObject jwsObject = new JWSObject(jwsHeader, payload);
    
            //建立一个密匙
    
            JWSSigner jwsSigner = new MACSigner(secret);
    
            //签名
            jwsObject.sign(jwsSigner);
    
            //生成token
            return jwsObject.serialize();
        }
    

    验证token

     //解析一个token
    
        public static Map<String,Object> valid(String token) throws ParseException, JOSEException {
    
    //        解析token
    
            JWSObject jwsObject = JWSObject.parse(token);
    
            //获取到载荷
            Payload payload=jwsObject.getPayload();
    
            //建立一个解锁密匙
            JWSVerifier jwsVerifier = new MACVerifier(secret);
    
            Map<String, Object> resultMap = new HashMap<>();
            //判断token
            if (jwsObject.verify(jwsVerifier)) {
                resultMap.put("Result", 0);
                //载荷的数据解析成json对象。
                JSONObject jsonObject = payload.toJSONObject();
                resultMap.put("data", jsonObject);
    
                //判断token是否过期
                if (jsonObject.containsKey("exp")) {
                    Long expTime = Long.valueOf(jsonObject.get("exp").toString());
                    Long nowTime = new Date().getTime();
                    //判断是否过期
                    if (nowTime > expTime) {
                        //已经过期
                        resultMap.clear();
                        resultMap.put("Result", 2);
    
                    }
                }
            }else {
                resultMap.put("Result", 1);
            }
            return resultMap;
    
        }
    

    调用的业务逻辑

    //生成token的业务逻辑
        public static String TokenTest(String uid) {
            //获取生成token
    
            Map<String, Object> map = new HashMap<>();
    
            //建立载荷,这些数据根据业务,自己定义。
            map.put("uid", uid);
            //生成时间
            map.put("sta", new Date().getTime());
            //过期时间
            map.put("exp", new Date().getTime()+6);
            try {
                String token = TokenUtils.creatToken(map);
                System.out.println("token="+token);
                return token;
            } catch (JOSEException e) {
                System.out.println("生成token失败");
                e.printStackTrace();
            }
            return null;
    
        }
    
        //处理解析的业务逻辑
        public static void ValidToken(String token) {
            //解析token
            try {
                if (token != null) {
    
                    Map<String, Object> validMap = TokenUtils.valid(token);
                    int i = (int) validMap.get("Result");
                    if (i == 0) {
                        System.out.println("token解析成功");
                        JSONObject jsonObject = (JSONObject) validMap.get("data");
                        System.out.println("uid是" + jsonObject.get("uid"));
                        System.out.println("sta是"+jsonObject.get("sta"));
                        System.out.println("exp是"+jsonObject.get("exp"));
                    } else if (i == 2) {
                        System.out.println("token已经过期");
                    }
                }
            } catch (ParseException e) {
                e.printStackTrace();
            } catch (JOSEException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] ages) {
            //获取token
            String uid = "kkksuejrmf";
            String token = TokenTest(uid);
            //解析token
            ValidToken(token);
        }
    

    总结

    JWT 的实践其实还是挺简单。安全性也是得到了保证,后端只需要保存着密匙,其他数据可以保存在token,由前端携带,这样可以减低后端的内心消耗。
    虽然token是加密的,但是携带的验证数据还是不要是敏感数据.

    相关文章

      网友评论

      • 五琴和弦:写的好,特意为你注册账号,点关注
        蓝汝丶琪:@五琴和弦 谢谢,希望你也分享文章,多多交流。

      本文标题:利用JWT生成Token

      本文链接:https://www.haomeiwen.com/subject/jjcdcftx.html