jwt如何防止token被窃取_SpringBoot系列之前后端接口安全技术JWT

本文详细介绍了JWT的原理、结构及其在SpringBoot中的应用。JWT是一种流行的跨域认证解决方案,由Header、Payload和Signature三部分组成。文章讨论了JWT与传统Cookie-Session认证机制的区别,并通过Java的JJWT库展示了如何在SpringBoot中实现JWT的创建和验证,包括配置、工具类和Spring Security的集成。
摘要由CSDN通过智能技术生成

3b12829c1127f1f70ab554401ac21806.png

 作者 |  smileNicky    

来源 | cnblogs.com/mzq123/p/13278935.html

1.什么是JWT?

JWT的全称为Json Web Token (JWT),是目前最流行的跨域认证解决方案,是在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519),JWT 是一种JSON风格的轻量级的授权和身份认证规范,可实现无状态、分布式的Web应用授权

引用官方的说法是:

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

引用官网图片,JWT生成的token格式如图:bca7d0690db50f6cab0fbd31fa8105da.png

2. JWT令牌结构怎么样?

JSON Web令牌以紧凑的形式由三部分组成,这些部分由点(.)分隔,分别是:

  • 标头(Header)

  • 有效载荷(Playload)

  • 签名(Signature)
    因此,JWT通常如下所示。xxxxx.yyyyy.zzzzzbca7d0690db50f6cab0fbd31fa8105da.png

ok,详细介绍一下这3部分组成

2.1 标头(Header)

标头通常由两部分组成:令牌的类型(即JWT)和所使用的签名算法,例如HMAC SHA256或RSA。
* 声明类型,这里是JWT
* 加密算法,自定义

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

然后进行Base64Url编码得到jwt的第1部分

Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2
的6次方等于64,所以每6个比特为一个单元,对应某个可打印字符。三个字节有24
个比特,对应于4个Base64单元,即3个字节需要用4个可打印字符来表示。JDK 中 提
供了非常方便的 B BA AS SE E6 64 4E En nc co od de er r和B BA AS SE E6 64 4D De ec co od de er r,用它们可以非常方便的完
成基于 BASE64 的编码和解码

2.2 有效载荷(Playload)

载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包
含三个部分:

  • (1)标准中注册的声明

    • iss (issuer):表示签发人

    • exp (expiration time):表示token过期时间

    • sub (subject):主题

    • aud (audience):受众

    • nbf (Not Before):生效时间

    • iat (Issued At):签发时间

    • jti (JWT ID):编号

  • (2)公共的声明
    公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息

  • (3)私有的声明
    私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。这些私有的声明其实一般就是指自定义Claim

定义一个payload:

{
    
    "user_id":1,
    "user_name":"nicky",
    "scope":[
        "ROLE_ADMIN"
    ],
    "non_expired":false,
    "exp":1594352348,
    "iat":1594348748,
    "enabled":true,
    "non_locked":false
}

对其进行base64加密,得到payload:

eyJ1c2VyX2lkIjoxLCJ1c2VyX25hbWUiOiJuaWNreSIsInNjb3BlIjpbIlJPTEVfQURNSU4iXSwibm9uX2V4cGlyZWQiOmZhbHNlLCJleHAiOjE1OTQzNTIzNDgsImlhdCI6MTU5NDM0ODc0OCwiZW5hYmxlZCI6dHJ1ZSwibm9uX2xvY2tlZCI6ZmFsc2V9

2.3 签名(Signature)

jwt的第三部分是一个签证信息,这个签证信息由三部分组成:

  • header (base64后的)

  • payload (base64后的)

  • secret
    签名,是整个数据的认证信息。一般根据前两步的数据,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第3部分

ok,一个jwt令牌的组成就介绍好咯,令牌是三个由点分隔的Base64-URL字符串,可以在HTML和HTTP环境中轻松传递这些字符串,与基于XML的标准(例如SAML)相比,它更紧凑。
下图显示了一个JWT,它已对先前的标头和有效负载进行了编码,并用一个秘密secret进行了签名编码的JWT:8a9fd53637ea2774ceb5b3339d4bde03.png

JWT官网提供的在线调试工具:
https://jwt.io/#debugger-io8427068c3f8e6b9493b160750e2a8a04.png
开源中国提供的base64在线加解密:
https://tool.oschina.net/encrypt?type=3981ddf86531d23d62dbcbab3867798c1.png

3. JWT原理简单介绍

引用官网的图,用于显示如何获取JWT,并将其用于访问API或资源:

cb0214fc554bc71dcef421a7cd7829d0.png

  • 1、客户端(包括浏览器、APP等)向授权服务器请求授权

  • 2、授权服务器验证通过,授权服务器会向应用程序返回访问令牌

  • 3、该应用程序使用访问令牌来访问受保护的资源(例如API)

4. JWT的应用场景

JWT 使用于比较小型的业务验证,对于比较复杂的可以用OAuth2.0实现

引用官方的说法:

  • 授权:这是使用JWT的最常见方案。一旦用户登录,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由,服务和资源。单一登录是当今广泛使用JWT的一项功能,因为它的开销很小并且可以在不同的域中轻松使用。

  • 信息交换:JSON Web令牌是在各方之间安全地传输信息的好方法。因为可以对JWT进行签名(例如,使用公钥/私钥对),所以您可以确保发件人是他们所说的人。此外,由于签名是使用标头和有效负载计算的,因此您还可以验证内容是否遭到篡改。

5. 与Cookie-Session对比

了解JWT之前先要了解传统的Cookie-Session认证机制,这是单体应用最常用的,其大概流程:

  • 1、用户访问客户端(浏览器),服务器通过session校验用户是否登录

  • 2、 用户没登录返回登录页面,输入账号密码等验证

  • 3、 验证通过创建session,返回sessionId给客户端保存到cookie

  • 4、接着,用户访问其它同域链接,都会校验sessionId,符合就允许访问

ok,简单介绍这套cookie-session机制,之前设计者开发这套机制是为了兼容http的无状态,这套机制有其优点,当然也有一些缺陷:

  • 只适用于B/S架构的软件,对于安卓app等客户端不带cookie的,不能和服务端进行对接

  • 不支持跨域,因为Cookie为了保证安全性,只能允许同域访问,不支持跨域

  • CSRF攻击,Cookie没做好安全保证,有时候容易被窃取,受到跨站请求伪造的攻击

ok,简单介绍了cookie-session机制后,可以介绍一下jwt的认证

  • 1、用户访问客户端(浏览器、APP等等),服务器通过token校验

  • 2、 用户没登录返回登录页面,输入账号密码等验证

  • 3、 验证通过创建已签名token,返回token给客户端保存,最常见的是存储在localStorage中,但是也可以存在Session Storage和Cookie中

  • 4、接着,用户访问其它链接,都会带上token,服务器解码JWT,如果Token是有效的则处理这个请求

网上对于cookie-session机制和jwt的讨论很多,可以自行网上找资料,我觉得这两套机制各有优点,应该根据场景进行选用,JWT最明显优点就是小巧轻便,安全性也比较好,但是也有其缺点。

  • 比如对于业务繁杂的功能,如果一些信息也丢在jwt的token里,cookie有可能不能保存。

  • 续签问题,jwt不能支持,传统的cookie+session的方案天然的支持续签,但是jwt由于服务端不保存用户状态,因此很难完美解决续签问题

  • 密码重置等问题,jwt因为数据不保存于服务端,如果用户修改密码,不过token还没过期,这种情况,原来的token还是可以访问系统的,这种肯定是不允许的,不过这种情况或许可以通过修改secret实现

6. Java的JJWT实现JWT

6.1 什么是JJWT?

JJWT是一个提供端到端的JWT创建和验证的Java库。永远免费和开源(Apache
License,版本2.0),JJWT很容易使用和理解。它被设计成一个以建筑为中心的流畅界
面,隐藏了它的大部分复杂性。

6.2 实验环境准备

环境准备:

  • Maven 3.0+

  • IntelliJ IDEA

技术栈:

  • SpringBoot2.2.1

  • Spring Security

新建一个SpringBoot项目,maven加入JJWT相关配置

<dependency>
            <groupId>io.jsonwebtokengroupId>
            <artifactId>jjwtartifactId>
            <version>${jjwt.version}version>
        dependency>
        <dependency>
            <groupId>com.auth0groupId>
            <artifactId>java-jwtartifactId>
            <version>${java.jwt.version}version>
        dependency>

pom.xml:

xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.2.1.RELEASEversion>
        <relativePath/> 
    parent>
    <groupId>com.example.springbootgroupId>
    <artifactId>springboot-jwtartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>springboot-jwtname>
    <description>Demo project for Spring Bootdescription>

    <properties>
        <java.version>1.8java.version>
        <jjwt.version>0.9.0jjwt.version>
        <java.jwt.version>3.4.0java.jwt.version>
        <mybatis.springboot.version>2.1.1mybatis.springboot.version>
    properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-securityartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>

        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>

        <dependency>
            <groupId>io.jsonwebtokengroupId>
            <artifactId>jjwtartifactId>
            <version>${jjwt.version}version>
        dependency>
        <dependency>
            <groupId>com.auth0groupId>
            <artifactId>java-jwtartifactId>
            <v
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值