• JWT笔记



    一、JWT的简介

    二、入门案例

    第一步:引入依赖

    <dependency>
    	<groupId>com.auth0groupId>
    	<artifactId>java-jwtartifactId>
    	<version>3.4.0version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    第二步:生成token

    package com.yx.jwt;
    
    import com.auth0.jwt.JWT;
    import com.auth0.jwt.algorithms.Algorithm;
    import org.junit.jupiter.api.Test;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.util.Calendar;
    import java.util.HashMap;
    import java.util.Map;
    
    class JWTDemoApplicationTests {
    
    	@Test
    	void contextLoads() {
    
    		Map<String,Object> map = new HashMap<>();
    
    		Calendar instance = Calendar.getInstance();
    		instance.add(Calendar.SECOND,20);
    		String token = JWT.create()
    				.withHeader(map) //header
    				.withClaim("userId", 21)
    				.withClaim("username", "zhangsan") //payload
    				.withExpiresAt(instance.getTime()) //指定令牌过期日期
    				.sign(Algorithm.HMAC256("@93!#49&$33"));//签名
    
    		System.out.println(token);
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    在这里插入图片描述

    第三步:根据令牌和签名解析数据

    	@Test
    	public void test(){
    		//创建验证对象
    		JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("@93!#49&$33")).build();
    
    		DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2ODUxMDcyNTcsInVzZXJJZCI6MjEsInVzZXJuYW1lIjoiemhhbmdzYW4ifQ.JN5Dq_7iUfcr7tQcaHLiCFZMb0Byr7rUkDvNKA_2xf0");
    
    		System.out.println(verify.getHeader());
    		//一个withClaim的拿取
    //		System.out.println(verify.getClaim("username").asString());
    		//多个withClaim的拿取 使用asInt必须的value是Int类型
    		System.out.println(verify.getClaims().get("userId").asInt());
    		System.out.println(verify.getClaims().get("username").asString());
    
    		System.out.println("过期时间"+verify.getExpiresAt());
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    JWT的工具肋封装

    package com.yx.jwt.utils;
    
    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.JWTVerificationException;
    import com.auth0.jwt.interfaces.DecodedJWT;
    
    import java.util.Calendar;
    import java.util.Map;
    
    public class JWTUtils {
    
        private static final String SING = "@93!#49&$33";
    
        /**
         *
         * 生成token header.payload.sing
         */
        public static String getToken(Map<String,String> map){
            Calendar instance = Calendar.getInstance();
            instance.add(Calendar.DATE,7);//默认7天过期
    
            //创建jwt builder
            JWTCreator.Builder builder = JWT.create();
    
            //payload
            map.forEach((k,v) ->{
                builder.withClaim(k,v);
            });
            String token = builder.withExpiresAt(instance.getTime()).sign(Algorithm.HMAC256(SING));//指定令牌过期时间
            return token;
        }
    
        /**
         * 验证token合法性
         */
        public static void verify(String token){
            DecodedJWT verify = JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
        }
    
        /**
         * 获取payload里的信息
         *
         */
        public static DecodedJWT getTokenInfo(String token){
            DecodedJWT verify = JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
            return verify;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    三、结合springboot

    第一步:引入依赖

    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0modelVersion>
    	<parent>
    		<groupId>org.springframework.bootgroupId>
    		<artifactId>spring-boot-starter-parentartifactId>
    		<version>2.7.13-SNAPSHOTversion>
    		<relativePath/> 
    	parent>
    	<groupId>com.examplegroupId>
    	<artifactId>jwt-springbootartifactId>
    	<version>0.0.1-SNAPSHOTversion>
    	<name>jwt-springbootname>
    	<description>jwt-springbootdescription>
    	<properties>
    		<java.version>1.8java.version>
    	properties>
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.bootgroupId>
    			<artifactId>spring-boot-starter-webartifactId>
    		dependency>
    
    		<dependency>
    			<groupId>org.mybatis.spring.bootgroupId>
    			<artifactId>mybatis-spring-boot-starterartifactId>
    			<version>2.2.0version>
    		dependency>
    
    		<dependency>
    			<groupId>com.alibabagroupId>
    			<artifactId>druidartifactId>
    			<version>1.1.19version>
    		dependency>
    
    		<dependency>
    			<groupId>mysqlgroupId>
    			<artifactId>mysql-connector-javaartifactId>
    			<version>8.0.29version>
    		dependency>
    		<dependency>
    			<groupId>org.projectlombokgroupId>
    			<artifactId>lombokartifactId>
    			<optional>trueoptional>
    		dependency>
    		<dependency>
    			<groupId>org.springframework.bootgroupId>
    			<artifactId>spring-boot-starter-testartifactId>
    			<scope>testscope>
    		dependency>
    
    		
    		<dependency>
    			<groupId>com.auth0groupId>
    			<artifactId>java-jwtartifactId>
    			<version>3.4.0version>
    		dependency>
    	dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.bootgroupId>
    				<artifactId>spring-boot-maven-pluginartifactId>
    				<configuration>
    					<excludes>
    						<exclude>
    							<groupId>org.projectlombokgroupId>
    							<artifactId>lombokartifactId>
    						exclude>
    					excludes>
    				configuration>
    			plugin>
    		plugins>
    	build>
    	<repositories>
    		<repository>
    			<id>spring-milestonesid>
    			<name>Spring Milestonesname>
    			<url>https://repo.spring.io/milestoneurl>
    			<snapshots>
    				<enabled>falseenabled>
    			snapshots>
    		repository>
    		<repository>
    			<id>spring-snapshotsid>
    			<name>Spring Snapshotsname>
    			<url>https://repo.spring.io/snapshoturl>
    			<releases>
    				<enabled>falseenabled>
    			releases>
    		repository>
    	repositories>
    	<pluginRepositories>
    		<pluginRepository>
    			<id>spring-milestonesid>
    			<name>Spring Milestonesname>
    			<url>https://repo.spring.io/milestoneurl>
    			<snapshots>
    				<enabled>falseenabled>
    			snapshots>
    		pluginRepository>
    		<pluginRepository>
    			<id>spring-snapshotsid>
    			<name>Spring Snapshotsname>
    			<url>https://repo.spring.io/snapshoturl>
    			<releases>
    				<enabled>falseenabled>
    			releases>
    		pluginRepository>
    	pluginRepositories>
    
    project>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115

    第二步:添加配置项

    
    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/jwt?characterEncoding=UTF-8&useSSL=false
    spring.datasource.username=root
    spring.datasource.password=root
    
    mybatis.type-aliases-package=com.example.jwt.entity
    mybatis.mapper-locations=classpath:mapper/*.xml
    
    logging.level.com.example.jwt.dao=debug
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    第三步:添加实体类

    package com.example.jwt.entity;
    
    import lombok.Data;
    import lombok.experimental.Accessors;
    
    @Data
    @Accessors(chain = true)
    public class User {
        private Integer id;
        private String username;
        private String password;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    第四步:添加持久层

    UserDao.java

    package com.example.jwt.dao;
    
    import com.example.jwt.entity.User;
    import org.apache.ibatis.annotations.Mapper;
    
    @Mapper
    public interface UserDAO {
        User login(User user);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    UserDAO.xml

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.example.jwt.dao.UserDAO">
        <select id="login" parameterType="User" resultType="User">
            select * from user where username = #{username} and password = #{password}
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    第五步:添加业务层

    UserService

    package com.example.jwt.service;
    
    import com.example.jwt.entity.User;
    
    public interface UserService {
    
        /**
         * 登录接口
         * @param user
         * @return
         */
        User login(User user);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    UserServiceImpl

    package com.example.jwt.service.impl;
    
    import com.example.jwt.dao.UserDAO;
    import com.example.jwt.entity.User;
    import com.example.jwt.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    @Service
    @Transactional
    public class UserServiceImpl implements UserService {
    
        @Autowired
        private UserDAO userDAO;
        @Override
        @Transactional(propagation = Propagation.SUPPORTS)
        public User login(User user) {
            User login = userDAO.login(user);
            if (login != null){
                return login;
            }
            throw new RuntimeException("登录失败~~");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    第六步:添加拦截器

    package com.example.jwt.interceptors;
    
    import com.auth0.jwt.exceptions.AlgorithmMismatchException;
    import com.auth0.jwt.exceptions.SignatureVerificationException;
    import com.auth0.jwt.exceptions.TokenExpiredException;
    import com.auth0.jwt.interfaces.DecodedJWT;
    import com.example.jwt.utils.JWTUtils;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.HashMap;
    import java.util.Map;
    
    public class JWTInterceptor implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            Map<String,Object> map = new HashMap<>();
            //获取请求头中的令牌
            String token = request.getHeader("token");
    
            try {
                DecodedJWT verify = JWTUtils.verify(token);
                return true;//放行请求
            } catch (SignatureVerificationException e) {
                map.put("msg","无效签名");
                e.printStackTrace();
            } catch (TokenExpiredException e){
                map.put("msg","token失效");
                e.printStackTrace();
            } catch (AlgorithmMismatchException e){
                map.put("msg","token算法不一致");
                e.printStackTrace();
            } catch (Exception e){
                map.put("msg","token无效!");
                e.printStackTrace();
            }
            map.put("state",false);
            //将map转为json jackson
            String json = new ObjectMapper().writeValueAsString(map);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().println(json);
            return false;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    第七步:添加配置类

    package com.example.jwt.config;
    
    import com.example.jwt.interceptors.JWTInterceptor;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    public class InterceptorConfig implements WebMvcConfigurer {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new JWTInterceptor())
                    .addPathPatterns("/user/test") //其他接口token验证
                    .excludePathPatterns("/user/login"); //所有用户都放行
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    第八步:测试

    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    JSON.stringify()的深入学习和理解
    第四代智能井盖传感器,实时守护井盖位安全
    Java-File类的介绍及使用
    关于本地项目连接git远程仓库以及git设置ignore文件
    面试题库(七):Spring相关
    Windows 10离线安装.NET Framework 3.5的方法技巧
    C++算法初级4——排列枚举
    某大厂软件测试岗一面笔试题+二面问答题面试经验分享
    RabbitMQ的stream流用法(output绑定通道 / input监听该通道的消息)
    5. Makefile项目管理
  • 原文地址:https://blog.csdn.net/weixin_43472934/article/details/130893821