# 简述内容

Cookie、Seesion、Token、JWT目标类似:都是用来做「身份认证 / 会话保持」,让服务器识别同一客户端;底层原理、存储位置、适用场景不同。

  • Cookie = 客户端存储工具(容器)
  • Session = 传统有状态认证(Cookie 存 sessionId,服务端存数据)
  • Token = 身份令牌统称(独立存储,放 Header)
  • JWT = Token 的一种标准化、自包含实现

通俗举例

  • Cookie = 你口袋(只能放小纸条)
  • Session 模式:柜台给你一张编号小票 (sessionId) 放你口袋 (Cookie),你的档案存在柜台后台;每次来出示小票,柜台翻档案确认你是谁。
  • Token:所有身份小票、证件的统称。
  • JWT 模式:柜台直接给你一张加密完整证件(JWT),证件上写清你的身份权限;柜台不用存档案,只核验证件真伪即可。

#.1.Cookie

  • 本质:浏览器自带的小型文本存储容器,由服务器下发、自动随请求携带。
  • 作用:存储少量键值对(会话 ID、用户偏好、token 等)。
  • 特点
    • 存在客户端浏览器
    • 每次 HTTP 请求自动带上;
    • 大小限制 4KB;
    • 有域、Secure、HttpOnly 安全限制;
  • 定位:存储载体,不是认证方案,只是存数据的盒子。

#.2.Session(服务端会话)

  • 本质:服务端维护的用户会话数据(内存 / Redis / 数据库)。
  • 完整流程
    1. 服务端生成唯一 sessionId
    2. 把 sessionId 放入 Cookie 返回浏览器;
    3. 浏览器下次请求自动带 Cookie,服务端拿 sessionId 查用户信息;
  • 作用:传统服务端会话登录方案,保存用户登录状态、权限。
  • 缺点
    • 服务端存数据,集群部署要共享 Session;
    • 依赖 Cookie,跨域麻烦;
  • 定位:基于 Cookie 的「服务端认证方案」

#.3.Token(通用术语,泛指令牌)

Token 是统称,代表一串身份凭证字符串,JWT 只是 Token 的其中一种实现。

  • 作用:替代 sessionId,客户端保存凭证,请求时手动携带(Header: Authorization);
  • 分类:不透明 Token(随机字符串,服务端查表)、透明 Token(JWT,自带信息);
  • 定位:通用身份凭证概念,独立于 Cookie。

#.4.JWT(JSON Web Token,Token 的一种标准实现)

  • 本质:加密签名后的 JSON 字符串,自带用户信息,不需要服务端查表。
  • 结构:Header + Payload (用户 ID、权限、过期时间) + 签名
  • 流程:登录后下发 JWT,前端存 Cookie/LocalStorage,每次请求放在请求头;服务器只用密钥校验签名,无需查询数据库 / Redis 获取用户信息。
  • 优点:无状态、适合分布式、前后端分离、跨端(小程序 / APP);
  • 缺点:无法中途注销(除非加黑名单)、Payload 不能存敏感数据;
  • 定位:无状态的标准化 Token 实现

维度 Cookie Session JWT(Token)
存储位置 浏览器本地存储介质 数据存服务端,ID 存 Cookie 完整令牌存在客户端 (Cookie/LS)
服务端状态 无业务状态,只是存储 有状态(需存储会话) 无状态(仅校验签名)
跨端适配 仅浏览器环境 APP / 小程序难用(依赖 Cookie) 全端通用(Header 携带)
数据容量 最大 4KB 服务端无限制 不宜过大,影响请求
数据是否自带用户信息 仅简单键值 不带,要查表 Payload 自带基础信息

1.Cookie

1.1.Cookie是什么

Cookie 是由网站存储在你浏览器中的一小段数据。它就像是网站给你的一张小便条,告诉浏览器在你下次访问时要记得某些信息。

由服务器端生成,发送给User-Agent ,浏览器会将Cookie的key/value自动保存到某个目录下的文本文件内,下次请求同一网站时就自动发送该Cookie给服务器。

目前Cookie已经成为标准,所有的主流浏览器如IE、Netscape、Firefox、Opera等都支持Cookie。

cookie默认根据域名自动判断是否带上cookie信息访问。

1.2.Cookie的工作原理

Cookie 的工作原理很简单,分为三个步骤:

  • 创建 Cookie:当你访问网站时,服务器会通过响应给你的浏览器发送 Cookie。
  • 存储 Cookie:浏览器接收到 Cookie 后,会把它存储起来。
  • 发送 Cookie:下次你访问该网站时,浏览器会把 Cookie 发送给服务器,这样服务器就能识别出是你在访问。

1.3.Cookie的应用场景

场景一:避免重复登录

当我们打开一个网站时,如果这个网站我们曾经登录过,网站会创建一个 Cookie 来保存你的登录信息。这样,即使你关闭浏览器,网站依然能记住你下次打开时已经登录过了。

场景二:权限验证

由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。

场景三:记住用户偏好

有些网站会记住你之前设置的语言或主题,这些偏好也通过 Cookie 来保存。当你下次访问时,网站会通过 Cookie 加载你的偏好设置。

场景四:购物车功能

在购物网站上,你可以将商品加入购物车,即使你没有登录账号或关闭了浏览器,下次回来时购物车里的商品依然还在。这就是通过 Cookie 来保存你的购物车信息。

    1.4.Cookie的组成

    一般情况下,cookie是以键值对进行表示的(key-value)的字符串

    cookie常用属性:

    • name:String cookie的名称,Cookie一旦创建,名称便不可更改。
    • value:Object cooke的值
    • path:String Cookie的使用路径, “/”
    • expires/maxAge:int cookie的有效时间,单位秒。默认为–1,浏览器关闭即失效。
    • domain:String 可访问该Cookie的域名,注意第一个字符必须为“.”。
    • secure:Boolean Cookie是否仅被使用安全协议传输,安全协议。
    • 注意:浏览器提交Cookie时只会提交name与value属性。

    cookie特点:

    • Cookie的不可跨域名性
    • cookie会被附加在每个HTTP请求中,所以无形中增加了流量。
    • 由于在HTTP请求中的cookie是明文传递的,所以安全性成问题。(除非用HTTPS)
    • Cookie的大小限制在4KB左右。对于复杂的存储需求来说是不够用的。

    1.5.Cookie的生命周期

    cookie有2种存储方式,一种是会话性,一种是持久性。

    • 会话性:如果cookie为会话性,那么cookie仅会保存在客户端的内存中,当我们关闭客服端时cookie也就失效了
    • 持久性:如果cookie为持久性,那么cookie会保存在用户的硬盘中,直至生存期结束或者用户主动将其销毁。
    • cookie我们是可以进行设置的,我们可以人为设置cookie的有效时间,什么时候创建,什么时候销毁。

    1.6.Cookie的使用

    1.6.1.客户端 Cookie

    JavaScript 可以使用 document.cookie 属性来创建 、读取、及删除(覆盖) cookie。

    document.cookie 将以字符串 (名/值对的形式展示)的方式返回所有的 cookie,类型格式如下:

    document.cookie="
      username=John Doe; 
      expires=Thu, 18 Dec 2043 12:00:00 GMT; 
      path=/
    ";
    
    document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";
    

    注意:从客户端读取Cookie时,包括maxAge在内的其他属性都是不可读的,也不会被提交。浏览器提交Cookie时只会提交name与value属性。maxAge属性只被浏览器用来判断Cookie是否过期。

    Cookie 方法的封装

    docCookies.setItem(name, value[, end[, path[, domain[, secure]]]])
    docCookies.getItem(name)
    docCookies.removeItem(name[, path], domain)
    docCookies.hasItem(name)
    docCookies.keys()
    

    设置 cookie 值的函数

    docCookies.setItem(name, value[, end[, path[, domain[, secure]]]])
    

    获取 cookie 值的函数

    let getCookie=key=> {
        //如果cookie中有数据  才可以获取数据
        if (document.cookie) {
          let cookieInfo = document.cookie;
          //cookie中可能会包含一些 额外的数据,这些数据特点是由   分号和空格间隔的
          //所以 先将 分号和空格  替换掉   替换成  ;
          let arr = cookieInfo.replace(/;\s/g, ';').split(";");
          let item,brr
          for (let i = 0; i < arr.length; i++) {
            item = arr[i].split("=");
            if (item[0] === key) {
              brr = item[1];
              return JSON.parse(brr);//如果找到 我们想要的键,将值转成数组返回
            }
          }
          //如果cookie中 没有我们想获取的键值,直接返回一个空数组
          return [];
        }
        //如果cookie中没有数据,直接返回一个空数组
        return [];
    }
    

    移除 cookie 值的函数

    let removeCookie=key=> {
        setCookie(key, "", -1);
    }
    

    检测 cookie 值的函数

    docCookies.hasItem(name)
    

    获取所有的cookie的列表

    docCookies.keys()

    返回一个这个路径所有可读的cookie的数组。

    function setCookie(name, value, path, domain, secure,expire){
      if(!expire){
         expire = expire*24*60*60;//365Ìì
      }
      var Days = 365; //cookie ½«±»±£´æ 365 Ìì
      var exp  = new Date();    //new Date("December 31, 9998");
      exp.setTime(exp.getTime() + expire*1000);
      document.cookie = 
         name + "=" + escape(value) + 
         ("; expires=" + exp.toGMTString() ) +
         ((path) ? "; path=" + path : "") +
         ((domain) ? "; domain=" + domain : "") +
         ((secure) ? "; secure" : "");
    }
      
    function getCookie(name){
      var dc = document.cookie;
      var prefix = name + "=";
      var begin = dc.indexOf("; " + prefix);
      if (begin == -1) {
         begin = dc.indexOf(prefix);
         if (begin != 0) return null;
      } else {
         begin += 2;
      }
      var end = document.cookie.indexOf(";", begin);
      if (end == -1) {
         end = dc.length;
      }
      return unescape(dc.substring(begin + prefix.length, end));
    }
    
    function deleteCookie(name, path, domain){
      if (getCookie(name)){
         document.cookie = name + "=" +
         ((path) ? "; path=" + path : "") +
         ((domain) ? "; domain=" + domain : "") +
         "; expires=Thu, 01-Jan-70 00:00:01 GMT";
      }
    }
    

    1.6.2.响应 Cookieresponse对象提供的Cookie操作方法只有一个添加操作。

    response.addCookie(cookie); 要想修改Cookie只能使用一个同名的Cookie来覆盖原来的Cookie,达到修改的目的。删除时只需要把maxAge修改为0即可。

    function getCookieByName(name) {
       const cookie = document.cookie;
       return cookie.split(`; ${name}=`).pop().split(';').shift();
    }
    

    1.7.Cookie的安全性

    虽然 Cookie 方便,但它有一定的安全隐患。比如,如果不小心让别人获取到你的 Cookie,他可能会冒充你登录某些网站。因此,在使用 Cookie 时,开发者通常会采取一些措施,比如:

    • 使用 HttpOnly 属性,防止 Cookie 被 JavaScript 获取。
    • 使用 Secure 属性,确保 Cookie 只能通过 HTTPS 传输,增加安全性。

    1.8.Cookie总结

    Cookie 是网站与用户之间保存信息的桥梁,能让网站记住你是谁、保存你喜欢的设置,还可以为你提供个性化的体验。虽然它在 Web 开发中用途广泛,但我们也需要注意保护好 Cookie 的安全。

    2.Session

    2.1.Session是什么

    Session 是服务器端用来记录用户状态的一种机制。Session 与 Cookie 不同,Cookie 是存储在用户浏览器中的,而 Session 是保存在服务器上的。

    简单来讲就是在一次会话中解决几次HTTP的请求的关联,让它们产生联系,让几个页面都能读取到找个这个全局的session信息。

    2.2.Session 的工作原理

    Session 的工作原理通常包含以下几个步骤:

    • 创建 Session:当用户第一次访问网站时,服务器会为该用户创建一个 Session,并生成一个唯一的标识符,称为 Session ID。
    • 存储 Session ID:服务器会通过 Cookie 或 URL 参数将 Session ID 发送给用户的浏览器。
    • 维护 Session:浏览器会在每次请求时,将 Session ID 发送给服务器,服务器根据这个 ID 找到对应的 Session,进而识别用户的状态。
    • 销毁 Session:当用户注销、关闭浏览器或 Session 过期时,Session 将被销毁,服务器不再保存用户的状态信息

    2.3.Session 的应用场景

    用户登录状态管理

    Session 的典型应用场景就是用户登录状态管理。当用户登录网站时,服务器会创建一个 Session 并存储用户的登录信息。接下来的每一次请求,服务器都可以通过 Session 来判断用户是否已经登录。

    购物车功能

    在电子商务网站中,Session 还常用于实现购物车功能。用户可以在浏览过程中将商品加入购物车,即使用户没有登录,Session 也能临时存储购物车信息。

    防止表单重复提交
    Session 还可以用于防止表单重复提交。当用户提交表单时,服务器可以生成一个唯一的令牌(token ),并将其存储在 Session 中。每次提交表单时,服务器会验证该令牌是否已经被使用过,从而避免重复提交。

    2.4.Session 的过期与销毁

    Session 通常有一定的生命周期 。用户关闭浏览器、网站设置的 Session 过期时间到了,或者用户主动注销时,Session 会被销毁。

    Session 过期时间
    在大多数 Web 应用中,Session 都有默认的过期时间。例如,在 Java Servlet 中,默认的 Session 过期时间为 30 分钟。如果用户在 30 分钟内没有与服务器交互,Session 将自动失效。

    // 设置 Session 过期时间为 15 分钟
    session.setMaxInactiveInterval(15 * 60);
    

    手动销毁 Session

    当用户退出登录时,通常会主动销毁 Session。这可以通过调用 invalidate() 方法来完成。

    // 销毁 Session
    HttpSession session = request.getSession();
    session.invalidate();
    

    2.5.Session 的安全性

    尽管 Session 主要是服务器端的机制,但也有一些安全隐患,比如 Session 劫持和 Session 固定攻击。以下是一些提升 Session 安全性的方法:

    • 使用 HTTPS:通过 HTTPS 传输 Session ID,可以防止中间人攻击窃取 Session。
    • Session ID 重生成:在用户登录后,重生成 Session ID,避免 Session 固定攻击。
    • 设置 Secure 和 HttpOnly:如果 Session ID 存储在 Cookie 中,确保使用 Secure 和 HttpOnly 属性,防止 Cookie 被 JavaScript 访问或通过非加密连接传输。

    2.6.Session总结

    Session 是 Web 开发中维护用户状态的一种重要机制,它能够在服务器端保存用户的登录状态、购物车信息等数据,并通过 Session ID 来识别每个用户的会话。相比 Cookie,Session 更加安全且适用于存储更多的用户数据。但我们在使用 Session 时,也需要注意它的安全性,防止用户的会话被劫持或篡改。

    # Cookie与Session核心差异对比

    对比维度

    Cookie

    Session

    核心本质

    客户端状态存储方案

    服务器端状态存储方案

    存储位置

    浏览器/客户端本地设备(内存/磁盘)

    服务器端(内存/文件/数据库/分布式缓存)

    生命周期管控

    1. 会话Cookie:浏览器关闭即销毁
    2. 持久化Cookie:通过Expires/Max-Age指定过期时间,不受浏览器关闭影响

    1. 由服务器设定超时时间(默认通常30分钟)
    2. 手动销毁(用户登出/服务端操作)
    3. 服务器重启/宕机默认丢失(持久化存储除外)
    4. 与浏览器关闭无直接关联

    存储限制

    1. 单域名下单Cookie最大约4KB
    2. 单域名下Cookie数量有浏览器限制(通常50个左右)
    3. 仅支持字符串类型键值对

    1. 无硬性容量上限,受服务器/缓存资源限制
    2. 无数量限制,可按需创建
    3. 支持任意数据类型(对象、数组、集合等)

    安全性基础

    存储在客户端,易被窃取、篡改、伪造,原生安全性低

    存储在服务器,数据不暴露给客户端,原生安全性高

    网络开销

    每次符合规则的同源请求,都会自动携带完整Cookie数据,体积越大带宽开销越高

    仅传递极小的SessionID,主体数据不参与网络传输,带宽开销极低

    跨域/跨站能力

    受同源策略严格限制,可通过Domain/Path/SameSite属性灵活控制跨域/跨站权限,支持跨子域配置

    默认仅当前服务实例生效,跨域/集群/分布式场景需额外做共享适配,原生不支持跨域

    依赖关系

    可完全独立使用,不依赖Session

    核心依赖SessionID的传递,默认使用Cookie存储SessionID,也可通过其他方式兼容,不强制依赖Cookie

    浏览器禁用兼容性

    用户禁用Cookie后,完全无法使用

    禁用Cookie时,可通过URL重写、表单隐藏字段传递SessionID,仍可正常使用

    分布式/集群兼容性

    天然兼容集群,只要域名一致,所有集群节点均可读取

    原生不兼容集群,需额外实现Session共享、集中式存储等方案

    3.Token

    3.1.Token是什么

    Token 直译是“令牌”,类比生活场景:你去电影院看电影,门票就是你的Token——凭门票(Token),工作人员能识别你是合法观众,允许你进入影院;看完电影后,门票失效,下次再看需要重新获取。

    3.2.Token的应用场景

    在编程和技术领域,Token的核心作用分两大场景,对应两种核心身份,吃透这两种,就能搞定80%的Token应用:

    身份认证Token:相当于“数字门票”

    这是最常见的Token场景,核心作用是「验证用户/设备的合法性」,替代传统的“用户名+密码”重复验证,提升安全性和效率。

    简单流程(以APP登录为例):

    • 用户输入用户名和密码,点击登录;
    • 服务器验证信息正确后,生成一串唯一的Token(包含用户ID、有效期等信息,经过加密处理);
    • 服务器将Token返回给客户端(APP/浏览器),客户端存储起来;
    • 后续用户请求数据时,客户端只需携带这串Token,服务器验证Token有效,就会返回数据,无需再次输入账号密码。

    核心优势:避免频繁传输用户名密码,降低泄露风险;Token可设置有效期,过期自动失效,安全性更高;支持多设备登录,每个设备对应唯一Token,方便管理。常见的JWT Token、Session Token,都属于这类。

    语法/语义处理Token:相当于“语言积木”

    这种Token很多人容易忽略,但其实每个程序员每天都在接触——它是编程语言、大模型处理文本的「最小单元」,就像积木一样,把复杂的代码、文本拆分成一个个可识别的“碎片”,方便程序解析和处理。

    举两个直观例子:

    • Python编译时:我们写的print("Hello Token"),会被Python解析器拆分成多个Token——print(标识符Token)、((分隔符Token)、"Hello Token"(字符串Token)、)(分隔符Token),解析器通过识别这些Token,才能理解代码的含义;
    • 大模型处理时:我们输入“用Python写一个简易计算器”,大模型会先把这句话拆分成Token(如“用”“Python”“写”“一个”“简易”“计算器”),再通过Token之间的关联,生成对应的代码,Token的拆分方式直接影响模型的理解和生成效果

    3.3.Token实现认证流程

    • 前端点击登陆,服务器验证账号密码是否正确
    • 正确后,服务器生成令牌(生成令牌的技术有很多,比如UUID等)
    • 将该令牌存到数据库或redis中,key是uuid(Token),value是userId
    • 把令牌返给客户端,客户端把令牌存在cookie中。
    • 以后请求的时候就把Token放在请求头里带上
    • 服务端收到请求后,从redis中验证该Token是否存在
    • 不存在,则说明用户未登录或登录过期
    • 存在获取value内容userId。根据userId查询数据库用户信息。
    • 如果数据库中存在userId用户,则说明认证成功,可以访问资源。

    3.4.优缺点

    优点

    • 可以隐藏真实数据,适当避免明文传输
    • 适用于分布式,解决Session共享问题

    缺点

    • 依赖Redis或数据库存储
    • 如果不使用第三方存储,那还不如使用Session

    3.5.为什么一定要用Token?3个核心原因,缺一不可

    不管是身份认证,还是语法处理,Token的存在都不是“多余的”,而是解决了技术领域的3个核心痛点:

    • 1. 安全性:替代明文传输,降低泄露风险
      • 如果没有Token,每次请求数据都要传输用户名和密码,这些明文信息在网络传输中很容易被拦截、窃取;而Token是加密 后的字符串,即使被拦截,没有解密密钥也无法获取用户信息,大幅提升安全性。
      • 比如我们用Python写后端接口,若不用Token,用户每次调用接口都要传账号密码,一旦接口被劫持,用户信息就会泄露;用Token后,只需传加密后的Token,且Token有有效期,风险大幅降低。
    • 2. 效率:减少重复验证,提升处理速度
      • 一方面,身份认证场景中,Token只需验证一次生成,后续请求无需重复验证账号密码,减少服务器的计算压力;另一方面,语法/大模型场景中,Token作为最小单元,能让解析器、大模型快速拆分、处理内容,提升效率。
      • 比如Python的tokenize模块,通过拆分Token解析代码,比直接解析完整字符串高效得多;大模型通过Token拆分文本,能快速捕捉语义,减少计算资源消耗。
    • 3. 灵活性:适配多场景,可扩展性强
      • Token的格式、有效期、携带方式都可以灵活配置,适配不同的应用场景:
        • 移动端APP:Token可存储在本地,离线状态下也能暂时使用,联网后再验证有效性;
        • Python后端:Token可设置不同权限,比如管理员Token能访问所有接口,普通用户Token只能访问基础接口;
        • 大模型:Token可根据文本复杂度动态拆分,平衡语义完整性和计算效率,甚至能通过Token优化,降低API调用成本。

    3.5.Token总结

    Token 是贯穿前后端认证体系的“数字信物”,它既作为用户登录后的临时通行证,也作为服务端权限校验的核心凭证。相比于有状态的 Session,Token 能有效解耦服务器资源,尤其适用于分布式与微服务架构。但在实践中,Token 的安全高度依赖存储方式与传输加密,我们需合理设置过期时间并防止泄露,才能确保这把“数字钥匙”安全可靠。

    4.JWT(JSON Web Token)

    4.1.JWT是什么

    JWT(JSON Web Token)是一种开放标准(RFC 7519),它定义了一种紧凑且URL安全的方式,用于在双方之间以JSON对象的形式安全地传输信息。简单来说,JWT就是一个经过编码和签名的字符串,它本身包含了用户信息(如用户ID、角色等),服务器可以通过验证这个字符串的签名来信任其中的信息-。

    JWT最常用于身份验证(Authentication)和授权(Authorization) 场景,特别适用于分布式站点的单点登录(SSO)场景-。由于JWT将用户信息加密到Token里,服务器本身不保存任何用户信息,因此它是一种无状态的认证解决方案-。

    官网https://jwt.io/

    4.2.JWT的组成

    一个JWT由三部分组成,中间用点号“.”分隔:

    Header.Payload.Signature

    例如:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

    1. Header(头部)

    Header是一个JSON对象,描述JWT的元数据,通常包含两部分:

    字段 说明 示例值
    alg 签名算法(Algorithm) HS256、RS256
    typ 令牌类型(Type) JWT

    例如:

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

    这部分经过Base64Url编码后形成JWT的第一部分。

    2. Payload(负载/载荷)

    Payload是JWT的主体部分,包含声明(Claims):即关于实体(通常是用户)和其他数据的声明。

    声明分为三类:

    (1)注册声明(Registered Claims) :标准预定义声明,推荐使用:

    声明 全称 说明
    iss Issuer 签发人
    exp Expiration Time 过期时间
    sub Subject 主题(用户ID)
    aud Audience 受众
    nbf Not Before 生效时间
    iat Issued At 签发时间
    jti JWT ID 唯一标识,用于防重放攻击

    (2)公共声明(Public Claims)自定义声明,应避免与已有标准冲突。

    (3)私有声明(Private Claims):通信双方约定的自定义声明。

    Payload示例:

    {
      "sub": "1234567890",
      "name": "John Doe",
      "admin": true,
      "iat": 1516239022,
      "exp": 1516242622
    }

    ⚠️ 重要提醒:Payload只是Base64Url编码,并未加密!任何人都可以解码读取内容,绝不能存放敏感信息(如密码)。

    3. Signature(签名)

    签名用于验证令牌的完整性和真实性。生成方式如下:

    signature = HMACSHA256(
        base64UrlEncode(header) + "." + base64UrlEncode(payload),
        secret_key
    )

    签名使用Header中指定的算法,将编码后的Header、编码后的Payload和一个只有服务器知道的密钥(Secret) 进行加密生成。这个签名可以确认JWT的发送者身份,并保证信息没有被篡改。

    4.3.JWT的原理与工作流程

    1. 核心原理

    JWT的核心思想是:服务器认证用户后,生成一个包含用户信息的JSON对象,加上签名后返回给客户端。客户端后续每次请求都携带这个JWT,服务器通过验证签名来确认用户身份,无需在服务器端保存任何会话数据

    2. 工作流程

    详细步骤

    • 用户登录:用户向服务器发送用户名和密码

    • 验证凭据:服务器验证账号密码是否正确

    • 生成JWT:服务器生成JWT(包含Header、Payload、Signature三部分)

    • 返回JWT:服务器将JWT返回给客户端

    • 客户端存储:客户端将JWT存储在localStorage、sessionStorage或Cookie中

    • 携带JWT请求:客户端每次请求都将JWT放在HTTP请求头的Authorization字段中(格式:Bearer <token>

    • 服务端验证:服务器验证JWT的签名和声明(过期时间、签发人等)

    • 返回响应:验证通过后,服务器处理业务逻辑并返回数据

    4.4.JWT的应用场景

    场景 说明
    用户身份验证 用户登录后,后续请求通过JWT验证身份
    单点登录(SSO) 用户在一个应用登录后,可在其他关联应用中使用同一JWT进行身份验证
    微服务架构 不同微服务之间通过JWT进行身份验证和授权,无需共享Session
    前后端分离应用 适合RESTful API的无状态认证
    API授权 第三方应用通过JWT访问受保护API资源

    4.5.JWT的优势与劣势

    优势 说明
    无状态(Stateless) 服务器不需要存储会话信息,易于水平扩展
    自包含(Self-contained) JWT包含用户信息,减少数据库查询次数
    跨域友好 Token可在不同服务间轻松传递和验证
    跨语言/跨平台 基于JSON的开放标准,多种编程语言支持
    防篡改 签名确保数据完整性
    防止CSRF攻击 Token不依赖Cookie存储,降低CSRF风险
    劣势 说明 缓解方案
    无法主动失效 Token签发后,在有效期内无法撤销 设置短过期时间 + 刷新令牌机制
    Payload内容可见 信息仅Base64编码,未加密 不存储敏感数据;必要时使用JWE加密
    令牌体积较大 增加网络传输开销 精简Payload内容
    密钥管理复杂 密钥泄露将导致严重安全问题 使用非对称加密(RS256),定期密钥轮换

    4.6.JWT总结

    JWT 是一种紧凑且自包含的无状态认证凭证,它以 JSON 为载体承载用户信息,并通过数字签名确保数据在传输过程中不被篡改。它无需服务器存储会话状态,能有效减轻服务端压力,天然适用于分布式系统和单点登录(SSO)场景。但 JWT 的负载默认仅被编码而未加密,且签发后无法主动撤销,使用时务必设置短期有效期、配合刷新令牌机制,并避免存放敏感数据。

    # JWT与Token的对比

    首先需要明确:Token是一个通用术语,可以指代任何表示身份的字符串;而JWT是Token的一种具体实现标准,具有更强的规范性和安全性。

    对比维度 传统Token JWT
    定义 泛指任何用于身份验证的令牌 遵循RFC 7519标准的特定Token格式
    结构 无固定格式,通常是随机字符串 固定三部分结构:Header.Payload.Signature
    信息存储 用户信息存储在服务端(数据库/Redis) 用户信息编码在Token自身(Payload)
    验证方式 每次请求需查询存储系统确认有效性 本地验证签名和声明,无需查库
    状态性 有状态——需记录Token状态 无状态——Token自带所有信息
    服务端压力 每次验证需查询数据库/Redis 验证仅需计算签名,压力小
    分布式支持 需要共享存储(如Redis)同步Session 天然适合分布式系统
    可撤销性 可随时删除存储中的记录使其失效 无法主动撤销,只能等待过期

    核心区别总结

    传统Token:服务器需要查库验证Token是否有效,是一种有状态的认证方式。

    JWT:服务器不需要查库,直接在服务端通过签名和声明进行校验,是一种无状态的认证方式。因为用户的信息已经在Payload中,签名也在Signature中,服务端只需使用密钥验证签名即可。

    参考文章链接:

    什么是 Cookie?简单介绍与使用方法-CSDN博客

    Cookie详解:原理、应用与管理-CSDN博客

    什么是 Session?如何应用?-CSDN博客

    【会话:Cookie与Session】Cookie与Session的区别(附对比表)_session cookie-CSDN博客

    吃透Token:看完彻底懂了!!!-CSDN博客

    JSON Web Token (JWT) 全面解析:原理、优缺点与最佳实践-CSDN博客

    JWT详细解析-CSDN博客

    Logo

    openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

    更多推荐