首页 > 其他分享 >JWT学习笔记

JWT学习笔记

时间:2023-02-21 11:45:20浏览次数:52  
标签:JWT mayikt jwt 笔记 学习 token import com

JWT学习笔记

JWT介绍

jwt 官网:https://jwt.io/

百度:JWT(JSON WEB Token)的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

JWT:Json Web Token,是基于Json的一个公开规范,这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息,他的两大使用场景是:认证数据交换

  • 认证:认证是JWT的最常用场景。只要用户完成登录,其随后的请求都会包含JWT,以允许用户访问经由当前JWT授权的路由、服务或者是资源。由于开销小且能够被简单应用在跨域访问上,JWT在分布式站点上所支持的单点登录(SSO)已经是当前它被广泛应用的一个特性。

  • 信息交换:JWT是一种在各参与方之间安全传递信息的良好方法。由于JWT可以被签名(例:使用公钥/秘钥对),因而可用于确认发送者自称的身份。除此之外,由于signature使用header和payload进行计算,也可以验证内容没有被篡改。

Session方案

是什么要用token?Session 存放在服务器端,Session ID无法实现共享

Token+Redis方案

解决Session集群无法共享的问题-->将token存到redis中

  • Token 类似于 Session ID
  • Token 依赖于 Redis 真实token存放value值

使用Token缺点:每次都需要根据token查询真实内容,对服务器端(比如Redis)压力就比较大。

JWT方案

JWT和token 最大的区别:

token依赖于Redis,token存放value数据比较安全;而JWT不需要依赖于服务器端,将数据信息内容直接存放在客户端(浏览器)

传统的token

传统的Token,例如:用户登录成功生成对应的令牌,key为令牌 value:userid,隐藏了数据真实性 ,同时将该token存放到redis中,返回对应的真实令牌给客户端存放。

客户端每次访问后端请求的时候,会传递该token在请求中,服务器端接收到该token之后,从redis中查询如果存在的情况下,则说明在有效期内,如果在Redis中不存在的情况下,则说明过期或者token错误。

JWT组成的部分

  1. Header(头) 作用:记录令牌类型、签名算法等 例如:

  2. Payload(有效载荷)作用:携带一些用户信息 例如

  3. Signature(签名)作用:防止Token被篡改、确保安全性 例如 计算出来的签名,一个字符串

1.第一部分:header (头部)

{
 Typ="jwt" ---类型为jwt
 Alg:"HS256" --加密算法为hs256
}

2.第二部分:playload(载荷) 携带存放的数据 用户名称、用户头像之类 注意敏感数据(不要存放未脱敏的信息,如手机号码、密码)

标准中注册的声明 (建议但不强制使用) :

  • iss: jwt签发者
  • sub: jwt所面向的用户
  • aud: 接收jwt的一方
  • exp: jwt的过期时间,这个过期时间必须要大于签发时间
  • nbf: 定义在什么时间之前,该jwt都是不可用的.
  • iat: jwt的签发时间
  • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

3.第三部分:Signature(签名)

验证签名,防止别人去篡改payload中的数据(基于md5)。

JWT优缺点

优点:

  • 无需再服务器存放用户的数据,减轻服务器端压力
  • 轻量级、json风格比较简单
  • 由于json的通用性,JWT天然支持 跨语言

缺点:

jwt一旦生成后期无法修改:

  • 无法更新jwt有效期(比如你想要让jwt 90天以后过期,但是你改变主意了,想让jwt提前60天过期,这是不可行的,原因是你的jwt生成好了是需要存放到客户端的,你无法修改客户端的数据。当然,如果用token实现的话就直接把redis的数据清理掉即可)
  • 无法销毁一个jwt(原因同上,jwt存放在浏览器客户端)

保护好secret私钥,该私钥对于鉴权非常重要。

不应该在jwt的payload存放敏感信息,因为客户端也可对称解密该部分信息,它相当于是暴露的。

JWT的应用场景

前端分离项目、(移动app、小程序、H5)

Base64

Base64 在线编码解码网站:https://base64.us/

Base64 相关概念:https://baike.baidu.com/item/base64/8545775?fr=aladdin

Base64不是加密和解密 主要是 编码和解码 基于64个可打印字符来表示二进制数据

header 头部(base64):

#将ewoidHlwIjoiand0IiwKImFsZyI6IkhTMjU2Igp9解码后的数据为:
{
"typ":"jwt",
"alg":"HS256"
}

ewoidHlwIjoiand0IiwKImFsZyI6IkhTMjU2Igp9

playload(base64):

作用:存放的数据

{
"userName":"mayikt",
"age":"28"
}

cGxheWxvYWQ=

secret=Base64(header .playload)

相关问题

token返回给客户端之后,服务端还要保存吗?

不需要保存

校验token时,怎么保证数据并没有被黑客拦截并篡改?

signature中有私钥来进行签名(即添加盐值),可以保证安全性

token颁发给客户端之后,要不要有过期时间?

需要设置token过期时间

多次登录生成的token都是一样的吗?都是可用的吗?

可以再payload加上时间戳,来保证每次生成的token都不一样,都是可用的

jwt和token区别?

jwt和token区别主要体现在接收的信息是否需要进入数据库查询信息。服务端验证客户端发来的token信息要进行数据的查询操作;而JWT验证客户端发来的token信息不需要, JWT使用密钥校验不用数据库的查询。

简单手写jwt

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.digest.Md5Crypt;

import java.io.UnsupportedEncodingException;
import java.util.Base64;

public class JWTDemo04 {

    public static void main(String[] args) throws UnsupportedEncodingException {
        // 手写jwt的案例
        /**
         * 1.头部
         * 2.payload
         * 3.验证签名
         */
        // jwt jwtHeader
        JSONObject jwtHeader = new JSONObject();
        jwtHeader.put("alg","HS256");
        jwtHeader.put("typ","jwt");
        // jwt playload
        JSONObject jwtPlayload = new JSONObject();
        jwtPlayload.put("userName","yushengjun644");
        jwtPlayload.put("age",22);

        //base64JwtHeader
        String base64JwtHeader= Base64.getEncoder().encodeToString(jwtHeader.toJSONString().getBytes());
        //base64JwtPlayload
        String base64JwtPlayload= Base64.getEncoder().encodeToString(jwtPlayload.toJSONString().getBytes());

        // 使用MD5 生成签名
        String jwtSecret="mayikt";  //签名key,即添加盐值,存放在服务端
        String signature = DigestUtils.md5Hex(jwtPlayload.toJSONString() + jwtSecret);
        String jwt=base64JwtHeader+"."+base64JwtPlayload+"."+signature;
        System.out.println(jwt);


        // 解密
        String jwtPlayloadStr=new String(Base64.getDecoder().decode(jwt.split("\\.")[1].getBytes()),    //为什么要加“//”,做转义,不然有可能会报错
                "UTF-8");
        String jwtsignatureStr=jwt.split("\\.")[2];
        System.out.println(DigestUtils.md5Hex(jwtPlayloadStr+jwtSecret).equals(jwtsignatureStr));
    }
}

实际项目整合jwt

maven依赖:

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

登录接口:

package com.mayikt.api.member;
import com.alibaba.fastjson.JSONObject;
import com.mayikt.api.base.BaseApiService;
import com.mayikt.api.base.BaseResponse;
import com.mayikt.api.member.dto.req.UserLoginDto;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

public interface JWTLoginService {
    /**
     * jwt登录的方式
     *
     * @return
     */
    @PostMapping("loginJwt")
    BaseResponse<JSONObject> loginJwt(@RequestBody UserLoginDto userLoginDto);

    /**
     * jwt 验证
     *
     * @return
     */
    @GetMapping("jwtVerification")
    BaseResponse<JSONObject> jwtVerification(@RequestParam("jwt") String jwt);
}
package com.mayikt.api.impl.member;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mayikt.api.base.BaseApiService;
import com.mayikt.api.base.BaseResponse;
import com.mayikt.api.impl.entity.UserInfoDo;
import com.mayikt.api.impl.mapper.UserInfoMapper;
import com.mayikt.api.impl.utils.MayiktJwtUtils;
import com.mayikt.api.member.JWTLoginService;
import com.mayikt.api.member.dto.req.UserLoginDto;
import com.mayikt.api.utils.MD5Util;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class JWTLoginServiceImpl extends BaseApiService<JSONObject> implements JWTLoginService {
    @Autowired
    private UserInfoMapper userInfoMapper;

    @Override
    public BaseResponse<JSONObject> loginJwt(UserLoginDto userLoginDto) {
        // 验证参数
        String mobile = userLoginDto.getMobile();
        if (StringUtils.isEmpty(userLoginDto.getMobile())) {
            return setResultError("mobile 不能为空!");
        }
        String passWord = userLoginDto.getPassWord();
        if (StringUtils.isEmpty(userLoginDto.getPassWord())) {
            return setResultError("passWord 不能为空!");
        }
        // md5加密
        String newPassWord = MD5Util.MD5(passWord);
        QueryWrapper<UserInfoDo> userInfoDoQueryWrapper = new QueryWrapper<>();
        userInfoDoQueryWrapper.eq("MOBILE", mobile);
        userInfoDoQueryWrapper.eq("PASSWORD", newPassWord);
        UserInfoDo userInfoDo = userInfoMapper.selectOne(userInfoDoQueryWrapper);
        if (userInfoDo == null) {
            return setResultError("手机号码或者密码错误");
        }
        // 生成jwttoken
        String jwt = MayiktJwtUtils.generateJsonWebToken(userInfoDo);
        JSONObject data = new JSONObject();
        data.put("jwt", jwt);
        return setResultSuccess(data);
    }

    @Override
    public BaseResponse<JSONObject> jwtVerification(String jwt) {
        if (StringUtils.isEmpty(jwt)) {
            return setResultError("jwt is null");
        }
        Claims claims = MayiktJwtUtils.checkJWT(jwt);
        if(claims==null){
            return setResultError("jwt error");
        }
        return setResultSuccess();
    }
}

Jwt如何实现注销

  1. 浏览器cookie清除(但是服务器还是存在)

  2. 建议将时间设置稍微短一点

  • jwt有效期 90天 无法提前过期
  • jwt保存在前端,所以当用户退出后无法清除jwt

文章参考自:

学习视频:【10分钟学会什么是jwt【余胜军通俗易懂版本】-哔哩哔哩】 https://b23.tv/HO8uemt

文档链接

https://note.youdao.com/ynoteshare/index.html?id=89b75af16d9d503dd606d6f1194137e0&type=note&_time=1676345277891

https://blog.csdn.net/u013343616/article/details/124924211

https://blog.csdn.net/Solo95/article/details/123456965

http://www.ujiuye.com/wenda/2021/70163.html

标签:JWT,mayikt,jwt,笔记,学习,token,import,com
From: https://www.cnblogs.com/galo/p/17140376.html

相关文章

  • git,repo学习
    Repo:就是一组git命令的集合,repoinit下载一个分支。repostart文件名--all本地传建的另一个代码分支,用于备份作用。比如:repostartzhao--allgit brach查看当前......
  • Springboot整合JWT封装工具类篇(二)
    前言:这里是将Springboot整合JWT测试篇(一)封装成工具类publicclassJWTUtils{//秘钥自己保管好privatestaticStringSECRET="token!Q@W3e4r";/**......
  • 如何通过使用vscode工具学习ts(typescript)
    1如果有vscode工具可自行忽略这条;如果没有vscode工具,可进入官网http://vscode.p2hp.com/进行下载,下载过程可自行百度。2D盘新建文件夹随意命名为TS-LEAN,然后再【终端】......
  • Springboot整合JWT测试篇(一)
    一、pom文件中引入依赖<!--引入jwt--><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.0</version></dependency>......
  • VUEX 使用学习三 : mutations
    转载请注明出处:在Vuex中store数据改变的唯一方法就是提交 ​​mutations​​​。​​mutations​​​里面装着一些改变数据方法的集合,这是Vuex设计很重要的一点,就......
  • VUEX 使用学习四 : action
    转载请注明出处:action用于处理异步任务;​​action​​,可以操作任意的异步操作,类似于​​mutations​​,但是是替代​​mutations​​来进行异步操作的。首先​​mutatio......
  • VUEX 的使用学习二: state
    转载请注明出处:state提供唯一的数据资源,所有的共享的数据都要统一放到store中的state中进行存储;状态state用于存储所有组件的数据。管理数据//初始化vuex对象c......
  • 软件工程个人学习心得
    Java应该是目前为止在软件开发领域使用最广的一种语言,学计算机的人员也始终绕不开Java。Java语言区别于其他语言的地方是,Java是在虚拟机上运行的,所以与平台无关,一串相......
  • openpyxl 笔记
     Python-Codebase/simpread-python处理excel完整版-简书.mdatmaster·dantefung/Python-Codebase(github.com) hexo_blog_config/Python操作Excel.mdatma......
  • 大一与大二软件工程专业学习心得与体会
    回顾即将两年的计算机专业大学生活,各种经历使我受益良多。在大一上半学期,我进行了c语言的学习。从老师的口中我得知,c语言是语言类中的基础,是我们成为一名成熟的程序员的第......