第十九章:使用JWT设计SpringBoot项目api接口安全服务JWT组成

JWT是一种用户双方之间传递安全信息的简洁的、URL安全的表述性声明规范。JWT(Json Web Token)作为一个开放的标准(RFC 7519),定义了一种简洁的、自包含的方法用于通信双方之间以Json对象的形式进行安全性信息传递,传递时有数字签名所以信息时安全的,JWT使用RSA公钥密钥的形式进行签名。

JWT组成

JWT格式的输出是以.分隔的三段Base64编码,与SAML等基于XML的标准相比,JWT在HTTP和HTML环境中更容易传递。(形式:xxxxx.yyy.zzz):

1、Header:头部 2、Payload:负载 3、Signature:签名

Header

在header中通常包含了两部分,Token类型以及采用加密的算法

Payload

Token的第二部分是负载,它包含了Claim,Claim是一些实体(一般都是用户)的状态和额外的数据组成。

Signature

创建签名需要使用编码后的header和payload以及一个秘钥,使用header中指定签名算法进行签名。

JWT工作流程图

JWT客户端发送请求到服务器端整体流程如下图1所示:

图1

本章目标

在SpringBoot项目中使用JWT作为接口安全框架,实现JWT生成以及验证。

构建项目

我们使用InteiiJ IDEA工具来构建一个SpringBoot项目,预先导入依赖Web、JPA、MySQL等,项目结构如下图2所示:

图2

添加JWT依赖

目前JWT支持多中变成语言,我们访问官网jwt.io/,在首页底部可以看到JWT所支持的所有编程语言以及对应的依赖包,我们选择io.jsonwebtoken(GitHub地址:github.com/jwtk/jjwt,目前已经更新到0.7.0版本了,我们添加最新的依赖到我们的pom.xml配置文件中,如下图3所示:

图3

我们只需要导入红框内的依赖即可,下面我们开始添加对应的数据库表结构。

数据库配置

我们将生成的Token存放到数据库中,要完成一整套的验证我们需要存储用户基本信息、Token基本信息两张表。

用户基本信息表

图4

可以看到上图4就是我们的用户信息表内的所有字段,其中我们可以添加自定义的字段如:ajax_bind_ip(ajax请求时绑定的客户端的IP地址)。

Token基本信息表

图5

我们保存的Token在数据库中是byte字节的形式存在,根据对应的appId生成一个Token。

application.yml

我们复制之前章节(第十三章:SpringBoot实战SpringDataJPA,文章底部源码链接)的application.yml配置文件到本章项目的resources目录下,如下图6所示:

图6

添加Druid依赖

修改pom.xml配置文件添加Druid的maven依赖,如下图7所示:

图7

创建用户实体

我们根据数据库内的用户基本信息表的字段构建出一个UserEntity,如下图8所示:

图8

创建Token实体

根据token基本信息表内的字段构建出TokenEntity实体,如下图9所示:

图9

我们实体创建完成后对应实体添加JPA,用于SpringDataJPA操作数据表信息。

创建UserJPA

图10

创建TokenJPA

图11

生成Token

我们的准备工作已经做完,下面开始实现生成Token的控制器,我们先来创建一个TokenController,如下图12所示:

图12

在编写获取Token的方法之前需要添加一个试图返回的类,方便我们在编写获取Token方法返回数据,如下图13所示:

图13

我们在TokenController控制器内添加获取Token的方法,如下图14、15、16、17、18所示:

图14

图15

图16

图17

图18

生成Token的方法比较长,所以还是建议下载源码查看,源码链接在文章底部。

生成Token方法的内容大致是,检查appId以及appSecret-->检查是否存在该appId的对应Token-->根据存在与否、过期与否执行更新或者写入操作-->返回用户请求。

在createNewToken方法中是JWT生成Token的方法,我们默认了过期时间为7200秒,上面是毫秒单位,我们生成token需要指定subject也就是我们的用户对象,设置过期时间、生成时间、还有签名生成规则等。token生成方法已经编写完成,下面我们需要在除了获取token的路径排除在外拦截所有的路径,验证路径是否存在header包含token,并且验证token是否正确,jwt会自动给我们验证过期,如果过期会抛出对应的异常。

Token验证拦截器

我们在拦截器中需要验证头信息,Token的值是否存在,Subject用户是否存在等。具体代码如下图19、20所示:

图19

图20

Claims就是我们生成Token是的对象,我们把传递的头信息token通过JWT可以逆转成Claims对象,并且通过getSubject可以获取到我们用户的appId。

配置拦截器

我们创建一个JWTConfiguration配置类,将我们创建的拦截器添加到SpringBoot项目中,如下图21所示:

图21

注意:我们配置JWT拦截器只拦截/api/下的所有路径。

运行测试

在启动项目之前我们先来配置一个IndexController,并且提供一个访问内容的API接口,如下图22所示:

图22

下面我们来启动项目,访问地址:127.0.0.1:8080/api/index,界面输出内容如下图23所示:

图23

我们在拦截器中配置的无论是不存在token还是token需要刷新都是返回"need refresh token"错误信息,下面我们在我们的用户信息表内添加一条测试数据,如下图24所示:

图24

其中密码也是使用到了byte字节的形式保存,具体内容我会放到项目源码resources目录下!下面我们通过/token地址获取jwt生成的token值,如下图25所示:

图25

可以看到我们可以正确的获取到JWT生成的token值,我们来看下是否存到数据库中。如下图26所示:

图26

可以看到我们数据库中已经有一条生成的Token值保存了,接下来我们使用获取到的Token通过Postman工具来访问我们的/api/index方法,如下图27所示:

图27

可以看到我们将之前获取的token作为请求header(X-YAuth-Token)的值进行传递,再次访问127.0.0.1:8080/api/index,就可以成功的获取接口返回的数据。

注意:如果Token过期,再次访问/jwt/token地址传入对应的appId以及appSecret就可以获取一条新的token,也会对应的更新数据库token信息表的内容。

总结

以上内容就是本章的全部讲解内容,本章主要讲解了SpringBoot项目如何加入JWT维护接口安全性,并且将JWT生成的Token存放到数据库中。

本章代码已经上传到码云:

SpringBoot配套源码地址:https://gitee.com/hengboy/spring-boot-chapter

SpringCloud配套源码地址:https://gitee.com/hengboy/spring-cloud-chapter

SpringBoot相关系列文章请访问:目录:SpringBoot学习目录

QueryDSL相关系列文章请访问:QueryDSL通用查询框架学习目录

SpringDataJPA相关系列文章请访问:目录:SpringDataJPA学习目录

SpringBoot相关文章请访问:目录:SpringBoot学习目录,感谢阅读!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏云计算教程系列

如何在Ubuntu 16.04上安装Webmin控制面板和模块

Webmin是一个Web界面,允许您通过浏览器管理配置文件和重新加载程序,而无需SSH连接到您的Linode。它是cPanel或Plesk等管理面板的流行替代品...

3613
来自专栏云计算教程系列

如何使用Python-GnuPG和Python 3验证代码和加密数据

GnuPG包提供用于生成和存储加密密钥的完整解决方案。它还允许您加密和签名数据和通信。

4258
来自专栏Samego开发资源

shell脚本加密 | shc

2213
来自专栏原创

个推推送iOS版 常见问题详解

1、提交了.p12文件后多久可以测试? 提交后10分钟左右才可以测试,并不是立即生效的。 2、应用在后台时接收不到消息,即APNS消息接收不到? 1.    先...

36711
来自专栏云计算教程系列

如何在Debian 9上为用户目录设置vsftpd

FTP是文件传输协议的缩写,是一种曾经广泛用于在客户端和服务器之间移动文件的网络协议。它已被更快,更安全,更方便的文件传输方式所取代。很多休闲互联网用户希望直接...

3094
来自专栏北京马哥教育

批量管理自动化运维100台小规模服务器

---- 目录 1.脚本背景介绍 2.脚本技术需求分析 2.1 SSH免登陆认证 2.2 Expect实现key分发 2.2 PSSH家族命...

1.6K15
来自专栏云计算教程系列

如何在Ubuntu 18.04上为用户目录设置vsftpd

FTP是文件传输协议的缩写,是一种曾经广泛用于在客户端和服务器之间移动文件的网络协议。它已被更快,更安全,更方便的文件传输方式所取代。许多普通网民希望通过htt...

1010
来自专栏令仔很忙

新手学Linux(六)----安装Nginx

nginx是C语言开发,建议在linux上运行,本教程使用Centos7.0作为安装环境。

1882
来自专栏LIN_ZONE

thinkphp5中使用phpmailer实现发送邮件功能(转载)

一、开启SMTP服务(使用php发送邮件需要用到SMTP服务,这里以163邮箱的SMTP服务为例)。

1081
来自专栏北京马哥教育

5分钟教你学会Django系统错误监控

django.utils.log.AdminEmailHandler为django处理系统日志发送邮件的handler

1393

扫码关注云+社区