jwt:快速上手

一、目录结构

在这里插入图片描述
创建一个普通的springboot 项目: springboot-jwt-demo

只需要加一个Spring Web的模块就ok

接下来咱们导入pom依赖

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

这个依赖是java jwt的依赖,里面帮我们封装了一些功能。咱们拿来使用即可

二、编写一个Jwt的工具包

JwtUtils

package com.xiaozhoubg.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.util.Base64Utils;

import java.util.Collections;
import java.util.Date;

public class JwtUtils {

    //2. 这里调用springboot的base64加密包,加密一个 字符串  ,因为一会我们要解密所以放到外部
    private static final byte[] KEY = Base64Utils.encode("Lanou3g".getBytes());

    //3. 自定定义一个方法,这样咱们现在只需要传用户id,时间自动3600秒(半小时)
    //如果说需要自己定义时间,那就调 1 方法即可。
    public static String newToken(Long id){
        return newToken(id,10);
    }

    //1. 创建一个变量 用户id ,过期时间秒 seconds 3600
    public static String newToken(Long id,long seconds){


        String token = Jwts.builder() //建造者方法
                .setId(String.valueOf(id)) //指定id值
                .setExpiration(new Date(System.currentTimeMillis() + seconds * 1000))//指定过期时间
                .addClaims(Collections.singletonMap("duration",seconds))
                .signWith(SignatureAlgorithm.HS256,KEY)//给签名指定算法 和密钥(base64加密的字符串)
                .compact();

        return token;
    }

//    4. 从token中取出id(用户id)
    //需要注意时,当token解析不出来的时候该方法会抛出异常(比如假token,过期token)
    public static Long getId(String token){
        //Claims是负载,也就是token的第二部分。也就是说咱们获取到他的负载
        Claims claims = (Claims) Jwts.parser()
                .setSigningKey(KEY)
                .parse(token)
                .getBody();

        String id =claims.getId();

        return Long.parseLong(id);
    }


//    用户登录,后台生成一个token,token返回给用户
//    用户每次请求都携带token,交给后台做验证
//    后台验证之后把token放到响应头再返回给用户
//    用户从响应头中取出token,更新本地的缓存

}

代码中的注释有详细的解释

三、测试类测试运行

咱们来编写一个测试类,这里有一个快捷方式创建测试类

在方法上面Alt+Enter 然后选生成test方法可以快速生成test方法
在这里插入图片描述

   @Test
   public void newToken() throws InterruptedException {
        String token = JwtUtils.newToken(10L, 10);
        System.out.println(token);


//        来测试 上面我们设置了token时长10秒
//        接下来咱们睡眠12秒再取,也就是说token过期了咱再取.发现方法抛出了异常
        Thread.sleep(12000);

        Long id = JwtUtils.getId(token);
        System.out.println(id);
    }

运行结果肯定是会报Jwt过期异常的,接下来咱们把 线程休眠 Thread.sleep(12000); 注释掉,再启动,控制台成功拿到 id 10

四、编写前端index.html

接下来咱们编写前端,直接引用在线jQuery即可,咱们用它的ajax

在我们上面列出的 static 静态文件下创建 index.html (模拟前后端分离)

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>jwt</title>
    <!-- 在线引用jQuery -->
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</head>
<body>
<!-- 写一个表单 -->
<form id="login-form" action="/login" method="post">

    用户名: <input type="text" name="username">
    密码: <input type="text" name="password">

    <input type="submit" >
</form>


<!-- 存好后第二部需要取了,从浏览器缓存取到token -->
<button id="btn-user-info">获取用户信息</button>

<script>
    $('#login-form').submit(function (form) {
        //这里要阻止表单默认提交事件
        form.preventDefault();
        //通过ajax发送登录请求
        var username =$('input[name=username]').val();//拿到账户密码然后存到data
        var password =$('input[name=password]').val();

        var data ={
            username:username,
            password:password,
        }//存到data,下面通过post发送到controller

        $.post('/login',data,function (resp) {
            console.log(resp)
            //登录之后把token存起来,这段代码的意思是将后端传过来的值resp.token传到 浏览器请求头缓存中,命名为token
            window.localStorage.setItem("token",resp.token);

        });
        })
    //这里是取token的方法
    $('#btn-user-info').click(function () {
        // 1.从缓存中取出token,
        var token = window.localStorage.getItem('token');
        // 2. 发送请求同时,把token放到请求头里
        console.log("wote??"+token)
        $.ajax({
            url:'/info',
            type:'get',
            headers:{
                token:token
            },
            success:function (resp) {
                console.log(resp)
            }
        })
    })
</script>
</body>
</html>

五、编写一个UserController

UserController

这里咱们模拟从数据库中查找出来的数据即可,并不影响什么,大家可以自己去加上数据库

package com.xiaozhoubg.controller;

import com.xiaozhoubg.utils.JwtUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.Map;

@RestController
public class UserController {

    //注意,这里咱们不用链接数据库自己定义一个数据做模拟即可,实际开发中再替换成数据库,相信
    //大家一定都知道如何替换成数据库。

    //登录
    @PostMapping("/login")
    public Map login(String username,String password){
        //接收前端传值并且判断 账户密码
        if ("admin".equals(username)&&"admin".equals(password)){
            //赋值id=1001
            Long id =1001L;
            //根据这个id 去 咱们之前的JwtUtils中newToken方法 生成 token 
            String token = JwtUtils.newToken(id);
            //创建好token后return回前端
            return Collections.singletonMap("token",token);
        }else {
            //账户密码错误返回异常
            return Collections.singletonMap("erro","用户名或者密码错误");
        }
    }

    //获取token
    //@RequestHeader 注解可以去拿请求头
    @GetMapping("/info")
    public Map userInfo(@RequestHeader String token){
		// 根据JwtUtils.getId方法去通过token拿到id,判断id是否正确
        if (1001L == JwtUtils.getId(token)){
            return Collections.singletonMap("user","admin");

        }else {
             return Collections.singletonMap("user","token失效");

        }

    }
}

六、运行测试

测试
在这里插入图片描述
接下来咱们点击 获取用户信息 在Network可以看到这个请求的请求头携带了token
在这里插入图片描述
在这里插入图片描述
控制台也打印出来了后台的传值,因为token正确,那如果token错误呢,会报个异常,只需要捕获一下就好了

总结
注意一下:JDK的版本问题,如果版本较高的话会影响最后的结果,希望大家引以为戒,推荐版本 JDK8.0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值