JSON Web Token 入门教程

Stella981
• 阅读 668

JWT是什么?

JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案。它是有三部分组成,示例如下,具体的讲解如下(jwt是不会有空行的,下面只是为了显示,便使用了换行看着比较方便)。

  1. eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.

  2. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjMfQ.

  3. SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

它是由一个"."号隔开、三部分组成。第一部分是header信息,

  1. {

  2. "alg": "HS256",// 加密的算法

  3. "typ": "JWT"// 加密的方式,填写JWT

  4. }

第二部分是Payload,有固定的六个部分和自定义数据组成,自定义数据看自己的情况需要来定义,是可以省去的。

  1. 'iss' => 'https://www.qqdeveloper.com',// 签发人

  2. 'exp' => time() + 86400,// 过期时间(这里的有效期时间为1天)

  3. 'sub' => '主题内容',// 主题

  4. 'aud' => '受众内容',// 受众

  5. 'nbf' => $time,// 生效时间

  6. 'iat' => $time,// 签发时间

  7. 'jti' => 123,// 编号

第三部分是Signature(是对前两部分加密得来的)。由于前两部分是公开透明的数据,因此防止数据的篡改和泄露,我们需要加密处理。首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

  1. 第一部分的加密方式(

  2. base64UrlEncode(header) + "." +

  3. base64UrlEncode(payload),

  4. secret)

最终生成的就是上面很长的一段字符串了。

为什么会使用JWT

这就需要从我们传统的认证模式来说了,传统的认证模式是基于session和cookie来实现用户的认证和鉴权。具体的流程模式如下图

JSON Web Token 入门教程

(图一)Session与Cookie认证与鉴权

1.客户端向服务端发送一个http请求。

2.服务端在收到客户端的请求时,生成一个唯一的sessionid,这里需要将该生成的session存储在服务端,这个sessionid存储具体的session内容,默认的是文件存储,当然我们可以修改具体的存储方式,例如数据库存储。3.客户端在接受到这个sessionid时,存在cookie里面,每次请求时携带该sessionid。4.服务端在接收到客户端的请求之后,根据客户端发送的sessionid来进行认证与授权。这里也推荐一下自己之前分享的一篇有关session于cookie的知识点。session与cookie详解

JSON Web Token 入门教程

(图二)传统的token授权

1.客户端向服务端发送一个http请求。

2.服务端在收到客户端的请求之后,生成一个唯一token,这里需要将该生成的token存储在服务端,至于怎么存,可以和上面session与cookie的方式一致。也可以存在缓存数据库中,如redis,memcached。3.服务端将该token返回给客户端,客户端存在本地,可以存请求头header中,也可以存在cookie中,同时也可以存在localstorage中。4.向服务端发送请求时,携带该token,服务端进行认证或者授

JSON Web Token 入门教程

(图三)JWT认证模式

1.客户端向服务端发送一个http请求。

2.服务端根据jwt的生成规则,生成一个token,并返回给客户端,这里服务端是不需要存储的。3.客户端在接受到该token时,存在客户端。4.客户端向服务端发送请求时,服务端对请求的token进行解析,如果发现解析出来的数据和生成的数据是一致的代表是一个合法的token,则进行相应的操作。

基于session和cookie的认证和鉴权模式有什么好与不好的地方呢?总结如下几点:

通过上面几张图,我们也大致可以看得出来,基于session都是需要服务端存储的,而JWT是不需要服务端来存储的。针对以上几点,总结如下:一、缺点 1.容易遇到跨域问题。不同域名下是无法通过session直接来做到认证和鉴权的。2.分布式部署的系统,需要使用共享session机制 3.容易出现csrf问题。

二、优点 1.方便灵活,服务器端直接创建一个sessionid,下发给客户端,客户端请求携带sessionid即可。2.session存储在服务端,更加安全。3.便于服务端清除session,让用户重新授权一次。

JWT与session有什么区别呢?

JWT是基于客户端存储的一种认证方式,然而session是基于服务端存储的一种认证方式。JWT虽然不用服务端存储了,也可以避免跨域、csrf等情况。但也存在如下几个不太好的地方。1.无法清除认证token。由于JWT生成的token都是存储在客户端的,不能有服务端去主动清除,只有直到失效时间到了才能清除。除非服务端的逻辑做了改变。2.存储在客户端,相对服务端,安全性更低一些。当JWT生成的token被破解,我们不便于清除该token。

如何使用JWT

这里推荐使用GitHub上面人家封装好的包,这里我使用的是firebase/php-jwt,在项目中直接使用即可安装成功。

  1. composer require firebase/php-jwt

接下来创建一个控制器,我这里使用的ThinkPHP5.1的框架

  1. use think\Controller;

  2. use Firebase\JWT\JWT;

  3. class Test extends Controller

  4. {

  5. private $key = 'jwtKey';

  6. // 生成JWT

  7. public function createJwt()

  8. {

  9. $time = time();

  10. $key = $this->key;

  11. $token = [

  12. 'iss' => 'https://www.qqdeveloper.com',// 签发人

  13. 'exp' => $time + 86400,// 过期时间(这里的有效期时间为1天)

  14. 'sub' => '主题内容',// 主题

  15. 'aud' => '受众内容',// 受众

  16. 'nbf' => $time,// 生效时间

  17. 'iat' => $time,// 签发时间

  18. 'jti' => 123,// 编号

  19. // 额外自定义的数据

  20. 'data' => [

  21. 'userName' => '编程浪子走四方'

  22. ]];

  23. // 调用生成加密方法('Payloadn内容','加密的键',['加密算法'],['加密的可以'],['JWT的header头'])

  24. $jwt = JWT::encode($token, $key);

  25. return json(['data' => $jwt]);

  26. }

  27. // 解析JWT

  28. public function analysisJwt()

  29. {

  30. try {

  31. $key = $this->key;

  32. $jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsImV4cCI6MTU2ODA5NjE4MCwic3ViIjoiXHU0ZTNiXHU5ODk4XHU1MTg1XHU1YmI5IiwiYXVkIjoiXHU1M2Q3XHU0ZjE3XHU1MTg1XHU1YmI5IiwibmJmIjoxNTY4MDA5NzgwLCJpYXQiOjE1NjgwMDk3ODAsImp0aSI6MTIzLCJkYXRhIjp7InVzZXJOYW1lIjoiXHU3ZjE2XHU3YTBiXHU2ZDZhXHU1YjUwXHU4ZDcwXHU1NmRiXHU2NWI5In19.kHb_9Np0zjE25YE9czUEGvmFPYtqMJT9tuZzJTuMZl0';

  33. // 调用解密方法('JWT内容','解密的键,和加密时的加密键一直','加密算法')

  34. $decoded = JWT::decode($jwt, $key, array('HS256'));

  35. return json(['message' => $decoded]);

  36. } catch (\Exception $exception) {

  37. return json(['message' => $exception->getMessage()]);

  38. }

  39. }

  40. }

通过访问第一个方法,可以生成下图一段字符串JSON Web Token 入门教程 我们将上图中的字符串复制到第二图中的$jwt变量,访问第二个方法即可解析出具体的数据。JSON Web Token 入门教程

本文分享自微信公众号 - 卡二条的技术圈(qq1005349393)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这