ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JWT、Token、MD5

2021-05-04 17:57:32  阅读:14  来源: 互联网

标签:String JWT mayikt jwt Token api import com MD5


Session、cookie、Token可看:session、cookie、token 详解

一、传统的Token

传统的token(也叫令牌)

在这里插入图片描述在这里插入图片描述传统的Token,例如:用户登录成功生成对应的令牌,key为令牌 value:userid,隐藏了数据真实性 ,同时将该token存放到redis中,返回对应的真实令牌给客户端存放。
客户端每次访问后端请求的时候,会传递该token在请求中,服务器端接收到该token之后,从redis中查询如果存在的情况下,则说明在有效期内,如果在Redis中不存在的情况下,则说明过期或者token错误。

二、jwt(json web token)

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

jwt和Token的区别

在这里插入图片描述

JWT组成的部分

小demo:

在这里插入图片描述

运行后得到了一个jwt:
在这里插入图片描述

把这串字符串复制到jwt官网进行解析:

在这里插入图片描述

1.Header(头)

作用:记录令牌类型、签名算法等 例如:{“alg":“HS256”,“type”,"JWT}

2.Payload(有效载荷)

作用:
就是存放jwt存放的数据内容
携带一些用户信息 例如
{
“userId”:“1”, //存放在客户端,不安全
“username”:“mayikt”
}

在这里插入图片描述

3.Signature(签名)

作用:防止Payload、Token被篡改、确保安全性 例如 计算出来的签名,一个字符串,就算MD5加密而已

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怎么办?答案:就算你获取了payload那么你也只能模拟,篡改不了的,因为他有签名的:

在这里插入图片描述

三、JWT优缺点

优点:

  1. 无需再服务器存放用户的数据,减轻服务器端压力
  2. 轻量级、json风格比较简单
  3. 跨语言
    缺点:
    jwt一旦生成后期无法修改:
  4. 无法更新jwt有效期
  5. 无法销毁一个jwt
    jwt 90天以后过期 提前60天过期(这种就改不了,因为jwt存在客户端,后期无法修改的。这是Token就有点优势了,因为token存在redis,你只要把redis清除了就可以改了

四、JWT的应用场景

前端分离项目、(移动app、小程序、H5)
Base64
Base64不是加密和解密 主要是 编码和解码 基于64个可打印字符来表示二进制数据
https://baike.baidu.com/item/base64/8545775?fr=aladdin
https://base64.us/

header 头部:
{
“typ”:“jwt”,
“alg”:“HS256”
}
ewoidHlwIjoiand0IiwKImFsZyI6IkhTMjU2Igp9
playload 存放的数据
{
“userName”:“mayikt”,
“age”:“28”
}
cGxheWxvYWQ=
secret=Base64(header .playload)
https://base64.us/

五、MD5:

在这里插入图片描述

六、简单手写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 {
        String jwtSecret="mayikt"; //盐存在服务器中的
        // 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());
        String base64JwtPlayload= Base64.getEncoder().encodeToString(jwtPlayload.toJSONString().getBytes());
        // 使用MD5 生成签名 后面再加盐(存在服务器,所以别暴力破解不了)
        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;/*
* 作    者 :蚂蚁课堂-余胜军
* 版 本 号 :v1.0.0.0
*******************************************************************
* 版权由每特教育-蚂蚁课堂-余胜军所有 微信yushengjun644 QQ644064779
* 官方网址:www.mayikt.com 
*******************************************************************
//----------------------------------------------------------------*/

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;/*
* 作    者 :蚂蚁课堂-余胜军
* 版 本 号 :v1.0.0.0
*******************************************************************
* 版权由每特教育-蚂蚁课堂-余胜军所有 微信yushengjun644 QQ644064779
* 官方网址:www.mayikt.com 
*******************************************************************
//----------------------------------------------------------------*/

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();
    }

}

http://127.0.0.1:7000/jwtVerification?jwt=

七、Jwt如何实现注销

  1. 浏览器cookie清除(但是服务器还是存在)
  2. 建议将时间设置稍微短一点

jwt有效期 90天 无法提前过期 (无法实现提前过期的,所以我们的jwt尽可能设的有效期短点
jwt 有效期180天 用户退出

本文来源:B站余胜军的,仅供本人复习使用

标签:String,JWT,mayikt,jwt,Token,api,import,com,MD5
来源: https://blog.csdn.net/GLOAL_COOK/article/details/116401882

专注分享技术,共同学习,共同进步。侵权联系[admin#icode9.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有