SpringSceurity(6)---JWT详解

在JWT之前我们在做用户认证的时候,基本上会考虑sessiontoken,所以在讲jwt之前,我们先来回顾下这个两个

一、传统的session认证

1、原理流程

session 是基于 cookie 实现的,session 存储在服务器端,sessionId 会被存储到客户端的cookie 中,具体流程如下

session 认证流程

1、用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建对应的 Session

2、请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器。

3、浏览器接收到服务器返回的 SessionID 信息后,会将此信息存入到 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名。

4、当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息,如果存在自动将 Cookie 信息也发送给服务端,服务端会 从 Cookie 中获取 SessionID,

再根据 SessionID 查找对应的 Session 信息,如果没有找到说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。

总结 根据以上流程可知,SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。

2、session 时需要考虑的问题

1、将 session 存储在服务器里面,当用户同时在线量比较多时,这些 session 会占据较多的内存,需要在服务端定期的去清理过期的 session。

2、当网站采用集群部署的时候,会遇到多台 web 服务器之间如何做 session 共享的问题。因为 session 是由单个服务器创建的,但是处理用户请求

的服务器不一定是那个创建 session 的服务器,那么该服务器就无法拿到之前已经放入到 session 中的登录凭证之类的信息了。

3、当多个应用要共享 session 时,除了以上问题,还会遇到跨域问题,因为不同的应用可能部署的主机不一样,需要在各个应用做好 cookie 跨域的处理。

4、sessionId 是存储在 cookie 中的,假如浏览器禁止 cookie 或不支持 cookie 怎么办?

5、移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token。

6、CSRF: 因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。

二、Token(令牌)

1、原理流程

基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息

这个不是标准时序图,能看懂大致意思就行。

token认证流程

1、客户端使用用户名跟密码请求登录。

2、服务端收到请求,去认证服务器验证用户名与密码。

3、验证成功后,服务端会签发一个 token 并把这个 token 发送给客户端。

4、客户端收到 token 以后,会把它存储起来,比如放在 cookie 里或者 localStorage 里。

5、客户端每次向服务端请求资源的时候需要带着服务端签发的 token。

6、服务端收到请求,然后去验证客户端请求里面带着的 token ,如果验证成功,就向客户端返回请求的数据。

2、token特点

1、如果你认为用数据库来存储 token 会导致查询时间太长,可以选择放在内存当中。比如 redis 很适合你对 token 查询的需求。

2、token 完全由应用管理,所以它可以避开同源策略。

3、token 可以避免 CSRF 攻击(因为不需要 cookie 了)

4、移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token

3、Token 和 Session 的区别

Session 是一种记录服务器和客户端会话状态的机制,使服务端有状态化,可以记录会话信息。而 Token 是令牌,访问资源接口(API)时所需要的资源凭证。Token

使服务端无状态化,不会存储会话信息。

有关Token 和 Session可以看下这篇博客 彻底理解cookie、session、token

三、JWT

我们在使用token的时候会发现,前端给我们传了token之后,我们还需要拿者这个token去数据库查询用户信息,并返回。这样数据库的操作肯定会影响一定的性能,

那jwt就是来解决这个的。

1、原理流程

JWT 认证流程

1、用户输入用户名/密码登录,服务端认证成功后,会返回给客户端一个 JWT。

2、客户端将 jwt 保存到本地(通常使用 localstorage,也可以使用 cookie)。

3、当用户希望访问一个受保护的路由或者资源的时候,需要请求头的 Authorization 字段中使用Bearer 模式添加 JWT,其内容看起来是下面这样 Authorization: Bearer jwt

4、服务端的保护路由将会检查请求头 Authorization 中的 JWT 信息,如果合法,则允许用户的行为。

因为 JWT 是自包含的(内部包含了一些会话信息),因此减少了需要查询数据库的需要,因为 JWT 并不使用 Cookie 的,所以你可以使用任何域名提供你的

API 服务而不需要担心跨域资源共享问题(CORS),因为用户的状态不再存储在服务端的内存中,所以这是一种无状态的认证机制。

2、Token 和 JWT 的区别

相同

1、都是访问资源的令牌

2、都可以记录用户的信息

3、都是使服务端无状态化

4、都是只有验证成功后,客户端才能访问服务端上受保护的资源

区别

Token 服务端验证客户端发送过来的 Token 时,还需要查询数据库获取用户信息,然后验证 Token 是否有效。

JWT 将 Token 和 Payload 加密后存储于客户端,服务端只需要使用密钥解密进行校验(校验也是 JWT 自己实现的)即可,不需要查询或者减少查询数据库,

因为 JWT 自包含了用户信息和加密的数据。

3、JWT特点

从优点来讲,它最大的优点就是,当服务端拿到JWT之后,我们不需要向token样还需去查询数据库校验信息,因为JWT中就包含用户信息,所以减少一次数据的查询,

但这样做也会带来很明显的问题

1、无法满足修改密码场景

因为上面说过,服务端拿到jwt是不会在去查询数据库的,所以就算你改了密码,服务端还是未知的。那么假设号被到了,修改密码(是用户密码,不是 jwt 的 secret)之后,

盗号者在原 jwt 有效期之内依旧可以继续访问系统,所以仅仅清空 cookie 自然是不够的,这时,需要强制性的修改 secret。

2、无法满足注销场景

传统的 session+cookie 方案用户点击注销,服务端清空 session 即可,因为状态保存在服务端。但 jwt 的方案就比较难办了,因为 jwt 是无状态的,服务端通过计算来校验

有效性。没有存储起来,所以即使客户端删除了 jwt,但是该 jwt 还是在有效期内,只不过处于一个游离状态。

3、无法满足token续签场景

我们知道微信只要你每天使用是不需要重新登录的,因为有token续签,因为传统的 cookie 续签方案一般都是框架自带的,session 有效期 30 分钟,30 分钟内如果有访问

,session 有效期被刷新至 30 分钟。但是 jwt 本身的 payload 之中也有一个 exp 过期时间参数,来代表一个 jwt 的时效性,而 jwt 想延期这个 exp 就有点身不由己了,因为

payload 是参与签名的,一旦过期时间被修改,整个 jwt 串就变了,jwt 的特性天然不支持续签!

四、JWT的结构

JWT由三部分组成,分别是 头信息有效载荷,签名 中间以 点(.) 分隔,具体如下

  xxxxx.yyyyy.zzzzz

1、header(头信息)

由两部分组成,令牌类型(即:JWT)、散列算法(HMAC、RSASSA、RSASSA-PSS等),例如:

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

然后,这个JSON被编码为Base64Url,形成JWT的第一部分。

2、Payload(有效载荷)

JWT的第二部分是payload,其中包含claims。claims是关于实体(常用的是用户信息)和其他数据的声明,claims有三种类型: registered, public, and private claims。

Registered claims:这些是一组预定义的claims,非强制性的,但是推荐使用, iss(发行人), exp(到期时间), sub(主题), aud(观众)等;

Public claims: 自定义claims,注意不要和JWT注册表中属性冲突,这里可以查看JWT注册表。

Private claims: 这些是自定义的claims,用于在同意使用这些claims的各方之间共享信息,它们既不是Registered claims,也不是Public claims。

示例

 {
"sub": "1234567890",
"name": "John Doe",
"admin": true
}

然后,再经过Base64Url编码,形成JWT的第二部分;

注意:对于签名令牌,此信息虽然可以防止篡改,但任何人都可以读取。除非加密,否则不要将敏感信息放入到Payload或Header元素中。

3、Signature(签名)

jwt的第三部分是一个签证信息,这个签证信息由三部分组成:header (base64后的)payload (base64后的)secret

这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。

var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);

var signature = HMACSHA256(encodedString, 'secret'); // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

将这三部分用.连接成一个完整的字符串,构成了最终的jwt:

 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

注意 secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,

在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

4、如何应用

一般是在请求头里加入Authorization,并加上Bearer标注:

fetch('api/user/1', {
headers: {
'Authorization': 'Bearer ' + token
}
})

参考

1、Cookie、Session、Token、JWT

别人骂我胖,我会生气,因为我心里承认了我胖。别人说我矮,我就会觉得好笑,因为我心里知道我不可能矮。这就是我们为什么会对别人的攻击生气。
攻我盾者,乃我内心之矛(24)

SpringSceurity(6)---JWT详解的更多相关文章

  1. 授权认证登录之 Cookie、Session、Token、JWT 详解

    一.先了解几个基础概念 什么是认证(Authentication) 通俗地讲就是验证当前用户的身份. 互联网中的认证: 用户名密码登录 邮箱发送登录链接 手机号接收验证码 只要你能收到邮箱/验证码,就 ...

  2. Json Web Token(JWT)详解

    什么是Json Web Token Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的 ...

  3. JWT详解

    目录 1.前言 2.JWT的数据结构 2.1 Header 2.2 Payload 2.3 Signature 2.4 Base64URL 3. JWT的实现   1.前言 定义:JSON Web T ...

  4. 全栈项目|小书架|服务器开发-JWT 详解

    JWT 官方简介:Introduction to JSON Web Tokens 文章基本是官网内容的翻译,英文不错的同学可点击上面的链接直接看英文文档. 什么是 JWT JWT全称是JSON Web ...

  5. JWT详解-(JSON Web Token教程)

    JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,本文介绍它的原理和用法. 一.跨域认证的问题 互联网服务离不开用户认证.一般流程是下面这样. 1.用户向服务器发送用户名和密 ...

  6. JWT(Json web token)认证详解

    JWT(Json web token)认证详解 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该to ...

  7. IdentityServer4实战 - JWT Token Issuer 详解

    原文:IdentityServer4实战 - JWT Token Issuer 详解 一.前言 本文为系列补坑之作,拖了许久决定先把坑填完. 下文演示所用代码采用的 IdentityServer4 版 ...

  8. 前后端分离,简单JWT登录详解

    前后端分离,简单JWT登录详解 目录 前后端分离,简单JWT登录详解 JWT登录流程 1. 用户认证处理 2. 前端登录 3. 前端请求处理 4. 后端请求处理 5. 前端页面跳转处理 6. 退出登录 ...

  9. JWT基础概念详解

    JWT基础概念详解 JWT介绍 之前我们文章讲过分布式session如何存储,其中就讲到过Token.JWT.首先,我们来回顾一下使用Token进行身份认证. 客户端发送登录请求到服务器 服务器在用户 ...

随机推荐

  1. python入门008

    目录 一.for循环 作用:for循环是因为在循环取值(即遍历值)时for循环比while循环的使用更为简洁 1.for循环语法: 2.应用案例: 注意:break 与 continue也可以用于fo ...

  2. 【高并发】面试官问我如何使用Nginx实现限流,我如此回答轻松拿到了Offer!

    写在前面 最近,有不少读者说看了我的文章后,学到了很多知识,其实我本人听到后是非常开心的,自己写的东西能够为大家带来帮助,确实是一件值得高兴的事情.最近,也有不少小伙伴,看了我的文章后,顺利拿到了大厂 ...

  3. day35 socket套接字介绍

    目录 一.套接字发展史与分类 二.套接字工作流程 三.基于tcp的套接字 一.套接字发展史与分类 套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD U ...

  4. scrapy 基础组件专题(十四):scrapy CookiesMiddleware源码

    一 Scrapy框架--cookie的获取/传递/本地保存 1. 完成模拟登陆2. 登陆成功后提取出cookie,然后保存到本地cookie.txt文件中3. 再次使用时从本地的cookie.txt中 ...

  5. JVM系列-方法调用的原理

    JVM系列-方法调用的原理 最近重新看了一些JVM方面的笔记和资料,收获颇丰,尤其解决了长久以来心中关于JVM方法管理的一些疑问.下面介绍一下JVM中有关方法调用的知识. 目的 方法调用,目的是选择方 ...

  6. 动手实现一个较为简单的MQTT服务端和客户端

    项目地址:https://github.com/hnlyf168/DotNet.Framework 昨天晚上大致测试了下 ,490个客户端(一个收一个发)  平均估计每个每秒60个包  使用mqtt协 ...

  7. Elasticsearch源码解析:环境搭建

    在之前学习Redis的过程中,我就是一边通过文档/视频学习,一边阅读源码.我发现两种方法可以相辅相成,互相补充.阅读文档可以帮助我们快速了解某个功能,阅读源码有助于我们更深入的理解这一功能的实现及思想 ...

  8. Netty 学习笔记(1) ------ Hello World

    服务端启动流程 package com.example.netty; import com.example.netty.handler.HelloServerHandler; import io.ne ...

  9. Monster Audio 使用教程(二)效果参数的保存

    点击左上角主菜单按钮,点击[保存]菜单,即可保存当前的所有效果参数. [另存为]菜单,则是把当前参数另存一个名称,然后通过[切换效果]菜单,实现效果的切换.  独立保存单个音轨的效果 点击音轨对应的[ ...

  10. android 官方教程地址和一个中文教程

    https://developer.android.google.cn/guide/components/fundamentals http://www.runoob.com/w3cnote/andr ...