JWT的原理与使用(包括与springboot整合)

1.什么是jwt

JWT是JSON Web Token的简写,以Json形式做为web应用中的令牌,用于在各方之间安全地将信息作为json对象传输,传输过程中可以完成数据加密、签名等相关处理。

2.jwt能做什么

1.授权。
2.信息交换。

3.jwt有何优势

传统的session认证方式将session保存在服务端(一般是内存),通过客户端cookie的sessionid来找到对应的session实现认证。此方式有如下缺点:
1.随着认证用户的增加,服务器内存会随着增加。
2.如果session保存在服务器内存中,下次登录必须再次请求存session的服务器才能进行认证,限制了应用的扩展能力。
3.cookie有被截获的风险。
4.sessionid表达的信息不丰富,不容易扩展。

jwt认证是将用户信息作为JWT Payload(负载),将其与头部(header)分别进行Base64编码拼接后签名,形成一个jwt,格式为header.payload. signature(签名)。
相对传统的session认证,有如下优势:
1.简洁:可通过post参数或者在header中发送,数据小传输快。
2.自包含:负载中包含了所有用户需要的信息,避免多次查询。
3.跨语言:因为是json加密的形式,基本适用任何web应用。
4.无须在服务端保存,更适合分布式系统。

4.jwt的结构

1.标头(header)
标头由两部分组成,令牌类型(默认jwt)和签名算法 ,使用base64(可逆编码,非加密)编成jwt的第一部分。
2.负载(payload)
包含了声明,声明是用户相关实体和其它数据的声明。同样使用Base64编码。
3.签名(signature)
签名是jwt的重点,由编码后的标头和负载加上密钥再使用签名算法(标头中指定的算法)签名后得出。
如果标头中的签名算法为a,编码后的标头为x,编码后的负载为y,密钥为z,签名就是a(x+"."+y,z)。而整个jwt就是x.y.a(x+"."+y,z)。

值得注意的是因为负载的编码可逆,负载里不能存放敏感信息。

5.JWT的使用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.封装工具类

public class JWTUtils {
    //密钥
    private static final String SING="!@#$%";

    /**
     * 生成token
     */
    public static String getToken(Map<String,String> map){
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE,7); //7天过期

        //创建Builder
        JWTCreator.Builder builder = JWT.create();
        
        //payload
        map.forEach((k,v)->{
            builder.withClaim(k,v);
        });

        String toekn = builder.withExpiresAt(instance.getTime())//过期时间
                .sign(Algorithm.HMAC256(SING));//签名
        return toekn;
    }

    /**
     * 验证TOKEN
     */
    public static void verify(String token){
        JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
    }

    /**
     * 获取token信息
     */
    public static DecodedJWT getTokenInfo(String token){
        DecodedJWT verify = JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
        return verify;
    }
}

7.整合springboot

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
以上实现了token的验证,但是每次都要传递token,可以用拦截器进行优化。
创建拦截类:

/**
 * JWT拦截器
 */
public class JWTInterceptor implements HandlerInterceptor {

    //处理请求前调用
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws IOException {
        Map<String, Object> map = new HashMap<>();
        //获取请求头中的token
        String token = request.getHeader("token");

        try {
            JWTUtils.verify(token);
            return true; //放行
        } catch (SignatureVerificationException e) { //签名异常
            e.printStackTrace();
            map.put("msg","无效签名");
        }catch (TokenExpiredException e) { //有效期异常
            e.printStackTrace();
            map.put("msg","token过期");
        }catch (AlgorithmMismatchException e) { //算法异常
            e.printStackTrace();
            map.put("msg","算法不一致");
        }catch (Exception e) {
            e.printStackTrace();
            map.put("msg","token无效");
        }
        map.put("state",false); //异常设置状态
        String json = new ObjectMapper().writeValueAsString(map); //将对象转换为Json字符串
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(json);
        return false;

    }
}

创建配置类:

/**
 * 拦截器配置类
 */
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(new JWTInterceptor()) //拦截器
                .addPathPatterns("/user/test") //拦截器的路径
                .excludePathPatterns("/user/login"); //不需要拦截的路径
    }
}

在这里插入图片描述
在这里插入图片描述


版权声明:本文为worilb原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。