jwt的使用

学习目标

1.加密
2.签名

起源

session变jwt token?
session的意义就是解决http的无状态请求,标志出每个请求对应的在线状态的用户。
问题是什么?我们有的服务是需要认证授权才能访问的,也就是用户在我们这边注册过,是我们服务的用户我们才服务。但是web每次请求

1.为什么http要是无状态的?
答:因为之前的http是有状态的,那么服务器就需要维持保存浏览器的状态,而且不知道浏览器的状态是什么时候断开,也就是什么时候关闭浏览器,这回造成服务器不断维持客户端信息等等,造成资源浪费,性能下降。
所以设计http无状态,浏览器随时访问,而且不保存当前浏览器的会话的状态信息,充分利用资源和性能。 也就是每次请求都当成一个未注册的新用户对待。 此时无状态的http抵达服务器的时候,服务器并不知道是那个会话状态的用户发送的。

2.所以,怎么判断是哪个用户发来的呢?
答:因为每次请求都当初未注册的新用户,顾我们可以让每次http都携带上username和password,相当于 ”用户每次想要我们服务她的时候,都需要说一句’我是会员’“,而我们会微笑的面对他说”好的,我查查我们的会员本先哈“,之后如果是会员 ”你好,我来服务你了会员哥哥“

总结:
她每次声称自己是会员,我每次查会员表。这就是http的简化版工作理解。

jwt能做什么? 加密和签名
#1.授权
一但用户登录,每个后续请求将包括jwt,从而允许用户访问该令牌允许访问的路由,服务与资源。
#2.信息交换 (签名可以防伪造)
安全的传输信息。因为可以对jwt进行签名(例如,公钥和密钥),所以你可以确保发件人是他们的本人(防伪造)。而且签名可以通过计算,判断内容是否进行了修改。

jwt的结构

x.y.z
x y是base64编码,转成字符串,谁都可以解码,并不是加密原则
疑问:那不是不安全吗?拦截后,使用你的token进行操作

jwt 生成和验签解码


import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Calendar;

@SpringBootTest
class DemoApplicationTests {

    /***
     * 生成token
     */
    @Test
    void contextLoads() {
        //1.不用设置头部,使用默认base64
        //2.设置载荷
//            2.1用户信息(名称,角色,权限)
//            2.2token过期时间
        //3.设置密钥 sign+密钥

        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.SECOND,2000);
        System.out.println(instance.getTime());
        String token = JWT.create()
//                .withHeader()头部不用设置,使用默认base64算法
                .withClaim("username", "小黑")
                .withClaim("userId", 21)
                .withExpiresAt(instance.getTime())
                .sign(Algorithm.HMAC256("!@E#DFKJDKG"));
        System.out.println(token);

    }

    /***
     * 验签
     */
    @Test
    void vertify(){
        //1.创建验签器,需要 ‘加密算法和密钥’
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("!@E#DFKJDKG")).build();
        //2.解码对象解码获取结构中数据
        DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NDg4Njc1MjcsInVzZXJJZCI6MjEsInVzZXJuYW1lIjoi5bCP6buRIn0.kgvAtcu7_WOGw_mSCmUqmBOyD8OaUUOAJWz5JHqvIcM");
        //3.通过解码对象获取jwt三大结构值
        //3.1 通过getClaims获取载荷信息值
        System.out.println(verify.getClaims().get("username").asString());
        System.out.println(verify.getClaims().get("userId").asInt());
        System.out.println(verify.getClaim("username").asString());
        System.out.println(verify.getHeader());
        System.out.println(verify.getSignature());
    }

}

jwtUtil

package com.example.shirodemo.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Calendar;
import java.util.Date;
import java.util.Map;

public class JwtUtil {

    private static final Logger log = LoggerFactory.getLogger(JwtUtil.class);

    /**
     * 过期时间5分钟
     */
    private static final long EXPIRE_TIME = 5 * 60 * 1000;

    /**
     * 生成签名,5min后过期
     *
     * @param username 用户名
     * @param secret   用户的密码
     * @return 加密的token
     */
    public static String sign(Map<String,String> map, String secret) {
        //两种时间过期方式
//        第一种:
//        Calendar instance = Calendar.getInstance();
//        instance.add(Calendar.SECOND,2000);
//        第二种
//        Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
        
        Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
        Algorithm algorithm = Algorithm.HMAC256(secret);
        JWTCreator.Builder builder = JWT.create();
        map.forEach((k,v)->{
            builder.withClaim(k,v);
        });
        String token = builder.withExpiresAt(date).sign(algorithm);
        return token;

    }

    /**
     * 校验token是否正确
     *
     * @param token  密钥
     * @param secret 用户的密码
     * @return 是否正确
     */
    public static boolean verify(String token, String username, String secret) {
        Algorithm algorithm = Algorithm.HMAC256(secret);
        JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username).build();
        try {

            DecodedJWT jwt = verifier.verify(token);
        } catch (JWTVerificationException e) {
            return false;
        }
        return true;
    }

    /**
         * 获得token中的信息:无需secret解密也能获得
     */
    public static String getUsername(String token) {
        return getClaim(token, "username");
    }

    public static String getClaim(String token,String username){
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(username).asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }
}

报错

无法序列化没有参数的对象,因为json没有{}对象,没有纯花括号的对象。
在这里插入图片描述

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值