从入门到运用,Jwt其实并不难!

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情
小Hub领读:

2018年写的一篇文章,哈哈哈,体验一下我当时的写作风格咧~


一般情况下,web项目都是通过session进行认证,每次请求数据时,都会把jsessionid放在cookie中,以便与服务端保持会话。

前后端分离项目中,通过token进行认证(登录时,生成唯一的token凭证),每次请求数据时,都会把token放在header中,服务端解析token,并确定用户身份及用户权限,数据通过json交互。

但是token一般都是UUID生成的一个随机码,作为一个key使用,从缓存中获取具体的用户信息。所以一般需要一个存储介质来保存token和用户信息。在一些场景中,如单点登录时候有点麻烦。

有没一种更方便的方式呢?答案是有的,就是我们今天要讲的jwt。jwt也算是一个特殊的token,不过jwt中自带了用户的相关信息,所以不需要存储介质,只需要验证签名保证安全的前提下就可以直接获取到用户的相关信息。

在讲jwt之前,我们先回顾一下session、token的相关内容。

session与cookie

我们都知道http是无状态的,所以需要某种机制来识别用户和保存用户的状态。而这个机制就是session。session是保存在服务端的,服务器通过session辨别用户,然后做权限认证等。

那如何才知道用户的session是哪个?这时候cookie就出场了,浏览器第一次与服务器建立连接的时候,服务器会生成一个sessionid返回浏览器,浏览器把这个sessionid存储到cookie当中,以后每次发起请求都会在请求头cookie中带上这个sessionid信息,所以服务器就是根据这个sessionid所以key获取到具体session。

google浏览器中查看cookie内容的方法有两个:

(一)F12,查看具体请求链接的请求头信息

(二)点击浏览器输入框的认证小锁,可以查看这个域名的相关cookie信息。

涉及到集群环境得话,session需要弄成分布式session,从而保证多个应用的会话状态一致性。spring项目可以使用spring session+redis来解决session共享问题。shiro项目可以重写redis版SessionDAO,把会话信息存到redis中实现共享。

(所以,明白没?)

接下来我们再来聊聊token。

Token

token,就是我们常说的用户身份令牌。只有涉及到受限资源的访问时候才需要身份令牌,所以,在访问开放资源时候http中是没有token的信息的,也即是说这时候会话是完全无状态的。token的是在用户登录以后生成的。用户登录之后我们会生成一个token作为key保存用户的信息并返回给客户端。保存方式set(token,用户信息)存储到redis等介质。之后客户端发起的请求只要在请求头中附带token的信息就可以完成身份认证。

开源项目renren-fast采用了前后分离的机制,使用token来完成身份认证,并且集成了shiro框架,所以想实战的可以去clone下来玩玩~

  • https://gitee.com/renrenio/renren-fast

(只能帮你到这了~)

好了,说了这么拓展知识,接下来我们进入我们的正题!jwt。

JWT

jwt是什么

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519)。该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。

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

jwt的特点

  • 简洁(Compact): 可以通过URL,POST参数或者在HTTP header发送,因为数据量小,传输速度也很快

  • 自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库或缓存。

说了这么多~

真面目:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

可能太长看不清,来个图片:

傻眼了吧?看不懂吧,哈哈哈哈哈~~~~~~~~~

那么我们一一把这串数据分析一下。

首先从jwt的消息结构开始分析:

jwt消息结构

jwt有3个组成部分,分别是

  • *头部(header) *

  • *载荷(payload) *

  • 签证(signature)

先回头看看jwt真面目那个例子。仔细点,认真点,有没在茫茫字母和数字中发现两个.(点号)。

就是这两个点号把jwt分成了3部分,分别对应着上面说的头部,载荷,签证。

先来讲讲头部:

Jwt的头部承载两部分信息:

  • 声明类型,这里是jwt

  • 声明加密的算法,通常直接使用HMACSHA256,就是HS256了

{"alg":"HS256","typ":"JWT"}

然后将头部进行base64编码构成了第一部分:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

(base64懂吧?) Base64是一种用64个字符来表示任意二进制数据的方法

Base64是一种任意二进制到文本字符串的编码方法,常用于在URL、Cookie、网页中传输少量二进制数据。

Java中可以使用java.util.Base64进行编码解码。

(我没骗你吧?头部就是这样来的)

然后我们看第二部分:载荷。

我依稀记得物理老师说过:直接施加在结构上的各种力,习惯上称为载荷(荷载)。

好了不吹牛了,这里是承载的意思。也就是说这里是承载消息具体内容的地方

内容又可以分为3中标准

  • 标准中注册的声明

  • 公共的声明

  • 私有的声明

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

  • iss: jwt签发者

  • sub: jwt所面向的用户

  • aud: 接收jwt的一方

  • exp: jwt的过期时间,这个过期时间必须要大于签发时间

  • nbf: 定义在什么时间之前,该jwt都是不可用的.

  • iat: jwt的签发时间

  • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

payload-公共的声明 :

公共的声明可以添加任何的信息。一般这里我们会存放一下用户的基本信息(非敏感信息)。

payload-私有的声明 :

私有声明是提供者和消费者所共同定义的声明。

需要注意的是,不要存放敏感信息,不要存放敏感信息,不要存放敏感信息!!!

因为:这里也是base64编码,任何人获取到jwt之后都可以解码!!(产品应该就不懂)

好了,请容许我Base64解码一下载荷部分内容到底是啥。

{"sub":"1234567890","name":"John Doe","iat":1516239022}

sub和iat是标准声明,分别代表所面向的用户和jwt签发时间。从上面我知道了:

  • 这个是发给一个账号是1234567890的用户(也许是ID)

  • 名字叫John Doe

  • 签发时间是1516239022(2018/1/18 9:30:22)

(牛逼~)

只剩下最后一部分了,待我一个闪现,外加一个大招秒杀它!

(emmmmm~~~,请求集合!!求救~)

签证部分貌似和Base64没啥关系呀,那到底是啥的~

SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

别急,先来说说签证用来干啥的,其实就是一个签名信息,使用了自定义的一个密钥然后加密后的结果,目的就是为了保证签名的信息没有被别人改过!(也就是保证jwt安全可用) 头部那里我们不是定义了一个加密算法么,就是它

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  (我的密钥)
)

也就是说,签证部分的信息有3个组成部分:

  • 头部-header (base64后的)

  • 载荷-payload (base64后的)

  • 密钥-secret

然后HMACSHA256只有两个参数,

  • base64后的头部 + "." + base64后的载荷

  • 密钥-secret

好了,这部分我就不做代码演示了。因为有现成的工具类可以直接用,哈哈

下面我们就介绍一下常用的生成jwt的工具类:

  • https://jwt.io/

以上就是官网给我们介绍的几种java可用的jar包。其中,io.jsonwebtoken是最常用的工具包。

使用步骤如下:

第一步,导入jar包:

<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

第二步:稍微封装一下,方便集成到项目中:

/**
 * jwt工具类
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2017/9/21 22:21
 */
@ConfigurationProperties(prefix = "renren.jwt")
@Component
public class JwtUtils {
    private Logger logger = LoggerFactory.getLogger(getClass());
    private String secret;
    private long expire;
    private String header;
    /**
     * 生成jwt token
     */
    public String generateToken(long userId) {
        Date nowDate = new Date();
        //过期时间
        Date expireDate = new Date(nowDate.getTime() + expire * 1000);
        return Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setSubject(userId+"")
                .setIssuedAt(nowDate)
                .setExpiration(expireDate)
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }
    public Claims getClaimByToken(String token) {
        try {
            return Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        }catch (Exception e){
            logger.debug("validate is token error ", e);
            return null;
        }
    }
    /**
     * token是否过期
     * @return  true:过期
     */
    public boolean isTokenExpired(Date expiration) {
        return expiration.before(new Date());
    }
    //getter、setter
}

生成jwt:

//生成token
String token = jwtUtils.generateToken(userId);

获取jwt的有效信息:

//获取载荷信息
Claims claims = jwtUtils.getClaimByToken(token);
if(claims == null || jwtUtils.isTokenExpired(claims.getExpiration())){
    throw new RRException(jwtUtils.getHeader() + "失效,请重新登录", HttpStatus.UNAUTHORIZED.value());
}
long userId = Long.parseLong(claims.getSubject())

嘿嘿、以上例子来自之前说个的renren-fast项目。所以呀,你还是去看看吧~

(又学了一个技能,好有成就感!)

使用场景

闲聊一下jwt的使用场景

详细可以看看这篇文章:https://baijiahao.baidu.com/s?id=1598976581711450442&wfr=spider&for=pc

总结

最后的最后,再来个小总结:

  1. 在Web应用中,别再把JWT当做session使用,绝大多数情况下,传统的cookie-session机制工作得更好

  2. JWT适合一次性的命令认证,颁发一个有效期极短的JWT,即使暴露了危险也很小,由于每次操作都会生成新的JWT,因此也没必要保存JWT,真正实现无状态。

至此,我想说的都说完了,我是吕一明,欢迎关注我公众号:MarkerHub。记得星标置顶我哇哈哈

(让我们一起摇摆~~)


(完)

MarkerHub文章索引:(点击阅读原文直达)

https://github.com/MarkerHub/JavaIndex
【推荐阅读】
超详细!4小时开发一个SpringBoot+vue前后端分离博客项目!!
点赞功能,用mysql还是redis?
网站发展历程九大阶段,及知识体系梳理

并不复杂,只需4步搞定Shiro集成redis实现会话共享
前方高能!如何自己手写一个热加载!

为什么重写了equals()也要重写hashCode()

好文章!点个在看!

JWT(跨域身份验证解决方案) 因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA、JavaScript、NodeJS、PHP等很多语言都可以使用。因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。它不需要在服务端保存会话信息, 所以它易于应用的扩展相比传统token的优势? 阅读详情

相关推荐

JWT入门 *JWT*,封装一个实用的 *JWT* 工具类

JSON Web 令牌 (JWT) 是一种开放标准 (RFC 7519),它定义了一种紧凑且独立的方式,**用于将信息作为 JSON 对象在各方之间安全地传输** 。此信息可以被验证和信任,因为它是经过数字签名的。JWT 可以使用密钥(使用 **HMAC** 算法)或使用 **RSA** 或 **ECDSA** 的公钥/私钥对进行签名。

ebb29bbe的博客 3113

jwt思维导图,让jwt不再难懂

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33805992的博客 266

浅析JWT| JWT是啥子,Java构建JWT

小声bbb 说到系统的安全识别,记得自己第一个项目,用的就是session,用户登录进来以后,给他session标记登录,记录id进去,轻轻松松,设计的操作也很简单,类似操作HashMap。 这大概也有1年多快两年了,现在回头看真的是可怕,几乎在裸奔 众所周知,平常使用的Session是存储在服务器的一种技术,可以理解为一个会话id,每次使用HTTP请求,都会携带一个sessionId,服务器根据这个SessionId去找对应的session しかし,我预判了你的预判 第三方完全可以随便输入一个sess

可乐的博客 4455

jwt token 鉴权验证

1. JWT介绍 本文是在TP6.0使用JWT的示例 JWT全称: JSON Web Token,以 token 的方式代替传统的cookie、session模式,用于各服务器、客户端传递信息及签名验证 2. 新增自定义函数fault() 在app/common.php中新增以下函数 /** * 抛出异常错误 * * @param string $msg * @param integer $code */ function fault(string $msg = "", $co...

404源码社区 - Admin404 4619

JWT(简介)

JWT工具类/*** JWT验证过滤器:配置顺序 CorsFilte->JwtUtilsr-->StrutsPrepareAndExecuteFilter**//*** JWT_WEB_TTL:WEBAPP应用中token的有效时间,默认30分钟*//*** 将jwt令牌保存到header中的key*/// 指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。// JWT密匙// 使用JWT密匙生成的加密key。

qq_65345936的博客 2529

JWT详解(文章内嵌jwt工具类)

JWT (JSON Web Token) 是目前最流行的跨域认证解决方案,是一种基于 Token 的认证授权机制。从 JWT 的全称可以看出,JWT 本身也是 Token,一种规范化之后的 JSON 结构的 Token。JWT 自身包含了身份验证所需要的所有信息,因此,我们的服务器不需要存储 Session 信息。这显然增加了系统的可用性和伸缩性,大大减轻了服务端的压力。

我认不到你的博客 4992

jwt jar包_从入门运用Jwt其实不难

小Hub领读:2018年写的一篇文章,哈哈哈,体验一下我当时的写作风格咧~一般情况下,web项目都是通过session进行认证,每次请求数据时,都会把jsessionid放在cookie中,以便与服务端保持会话。前后端分离项目中,通过token进行认证(登录时,生成唯一的token凭证),每次请求数据时,都会把token放在header中,服务端解析token,确定用户身份及用户权限,...

weixin_39908616的博客 2694

jwt token 附加用户信息_从入门运用Jwt其实不难

小Hub领读:2018年写的一篇文章,哈哈哈,体验一下我当时的写作风格咧~一般情况下,web项目都是通过session进行认证,每次请求数据时,都会把jsessionid放在cookie中,以便与服务端保持会话。前后端分离项目中,通过token进行认证(登录时,生成唯一的token凭证),每次请求数据时,都会把token放在header中,服务端解析token,确定用户身份及用户权限,...

weixin_28909161的博客 1211

jwt认证入门整合shiro

目录 什么是JWT 为什么使用JWT 基于token的鉴权机制 JWT的结构 JWT令牌的有点 jwt的签发和验证(jwt入门) SpringBoot下Shiro整合JWT实现权限校验 配置shiro 配置JWT 用postman测试工具测试程序 总结 参考文章 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于J...

xrMrwhile的博客 1720

JWT入门以及常见的登录问题

本文主要介绍了JWT是什么,如何使用JWT以及实际开发中可能会遇到的有关JWT登录问题,比如token的续签、续期和登出问题等。

霁晨晨晨的博客 4万+

什么是JWT?新手5分钟入门JWT的使用

JSON Web Token(JWT)是一种开放标准(RFC7519),它定义了一种紧凑而独立的方式,用于在各方之间作为JSON对象安全地传输信息。此信息是可以验证和信任的,因为它是经过数字签名的。

CodeJR 1万+

Spring Security 超详细整合 JWT,能否拿下看你自己!

文章目录1.JWT 入门1.1 JWT 概念1.2 JWT 应用场景1.3 为何选择 JWT基于 Session 的传统认证基于 JWT 的认证1.4 JWT 的结构标头(Header)载荷(Payload)签名(Signature)1.5 RBAC (Role-Based Access Control)1.6 JWT 基本使用添加依赖生成 Token解析 Token2.Security 整合 JWT2.1 单独抽离 Security 模块添加相关依赖JWT 工具类JWT 相关配置JWT 登录授权过滤器自定

1万+

认识使用JWT

注意:不要把秘密信息放在这个JSON对象中,因为通常这个JSON对象被转换为字符串后,默认是不加密的,这就会被别人解析回JSON对象,里面的信息就暴露了。(1)alg属性表示签名的算法,默认是 HMAC SHA256(写成 HS256);(2)typ属性表示这个令牌(token)的类型,JWT统一写为"JWT"。(2)exp (expiration time):过期时间。(6)iat (Issued At):签发时间。(1) iss (issuer):签发人。(3)sub (subject):主题。

南七行者的博客 1074

JWT入门到精通

JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。

weixin_46228563的博客 1067

JWT讲解与实际运用

本篇博客是借鉴一位大佬的博客的,目的是自己手敲一遍能够记得更加深刻,同时也是以防万一那位大佬把博客删了,以后就看不了这么好的文章了。一开始的时候没有注意到JWT技术,直到前几天面试的时候,面试官问到了这个问题,当时当场就懵了,所以这次来补一下。JWT详解客户端使用用户名和密码请求登录。服务端收到请求后,验证用户名和密码。验证成功后,服务端会签发一个token,然后再把token返回给客户端。客户端收到token后可以把它存储起来,比如放到cookie中。

m0_73845616的博客 2138

我不应该用JWT的!

JWT: 生成发给客户端之后,后台是不用存储,客户端访问时会验证其签名、过期时间等再取出里面的信息(如username),再使用该信息直接查询用户信息完成登录验证。jwt自带签名、过期等校验,后台不用存储,缺陷是一旦下发,服务后台无法拒绝携带该jwt的请求(如踢除用户);Token+Redis: 是自己生成个32位的key,value为用户信息,访问时判断redis里是否有该token,如果有,则加载该用户信息完成登录。

summon的博客 2534

Java中JWT(JSON Web Token)的运用

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用环境间以紧凑的方式安全地传递信息。JWT可以被用作身份验证和信息交换的手段,特别适合用于前后端分离的应用程序。Signature(签名): 用于验证消息的完整性和发送者的身份。好的,让我们更详细地探讨如何在Java Spring Boot应用程序中实现JWT身份验证,包括每一步的代码和说明。Header(头部): 通常包含令牌的类型(JWT)和所使用的签名算法(如HMAC SHA256或RSA)。

m0_74823827的博客 887

JWT入门详解

目录 一、JWT简介 1.什么是JWT? 2.为什么要使用JWT? 二、JWT的工作原理 三、JWT的组成 1.Header(头部) 2.Payload(载荷) Reserved claims(保留) Public claims(公有) Private claims(私有) 3.signature 四、JWT的验证过程 五、JWT令牌刷新思路 1.首先前后端跨域配置 2.JWT配置 3.配置JWT验证过滤器 4.登陆方法成功后,将生成的JWT令牌通过响应头返回给客户端 .

weixin_57504000的博客 5037
上一篇: 超详细!4小时开发一个SpringBoot+vue前后端分离博客项目!!
下一篇: 从零开始搭建创业公司后台技术栈
MarkerHub
博客等级 码龄6年 342粉丝 77原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值