首页 > 其他分享 >web中两种登录状态保存方式:JWT和Session

web中两种登录状态保存方式:JWT和Session

时间:2023-11-29 15:24:26浏览次数:32  
标签:web 请求 Session JWT header session cookie 服务端

由于http是无状态的,也就是说上一次请求和下一次请求之间没有任何关联。
那如何实现登录状态的保存呢?

一般使用两种方案:

  1. 服务端存储的session + cookie的方案
  2. 客户端存储的jwt token的方案

但是这两种方式都有各自的缺点。

给http加状态,那就给每个请求打上标记(cookie),然后在服务端存储这个标记对应的数据(session)。这样每个被标记的请求就可以找到对应的数据,自然就可以做到登录,权限等状态的存储。


这个标记是在每次请求中自动带上的,所以Http设计了cookie的机制;
然后根据cookie里的标记去查找的服务端对应的数据叫做session,这个标记就是sessionid

如图,因为每次请求自动带上cookie,那这两次请求就都可以找到id为1对应的session,自然就知道当前登录的用户是谁,也可以存储其他状态数据。
这就是session+cookie的给http添加状态的方案
这种方案最的问题就是 CSRF(跨站请求伪造):

CSRF

因为cookie会在请求时自动带上,如果用户在网站A登陆过,再访问网站B,如网站B中有个按钮会请求网站A,那么cookie依旧会带上,这时候就不用再登录了。
万一点击这些按钮会很危险。
为了解决这个问题,我们一般会验证 referer,就是请求是哪个网站发起的,如果发起请求的网站不对,那就阻止掉。
但这样依然不能完全解决问题,万一你用的浏览器也是有问题的,能伪造 referer 呢?
所以一般会用随机值来解决,每次随机生成一个值返回,后面再发起的请求需要包含这个值才行,否则就认为是非法的。
这个随机值叫做 token,可以放在参数中,也可以放在 header 中,因为钓鱼网站拿不到这个随机值,就算带了 cookie 也没发通过服务端的验证。
这是 session + cookie 这种方案的一个缺点,但是是有解决方案的。
它还有别的缺点,比如分布式的时候:

分布式session:

session是把状态数据保存在服务端,如果有多台服务器,那服务器之间如何同步session

例如:登录之后的session是保存在服务器A的,但是某个功能会访问到服务器B,这时候服务器B是没有对应的ssession的,就没法完成对应都的功能。
这种问题有两个解决方案:

  1. session 复制,也就是通过一种机制在各台机器自动复制 session,并且每次修改都同步下。这个有对应的框架来做,比如 java 的 spring-session。
  2. 把 session 保存在 redis,这样每台服务器都去那里查,只要一台服务器登录了,其他的服务器也就能查到 session,这样就不需要复制了


    分布式会话的场景,redis+session的方案更常用一点

session + cookie 还有跨域的问题:

跨域

cookie是为了安全,是做了domain的限制的,设置cookie的时候会指定一个 domain,只有这个 domain的请求才会带上cookie。
而且还可以设置过期时间,路径等等:

那万一是不同 domain 的请求呢?也就是跨域的时候,怎么带 cookie 呢?
a.xxx.com 和 b.xxx.com 这种还好,只要把 domain 设置为顶级域名 xxx.com 就可以了,那二三级域名不同也能自动带上。

但如果顶级域名也不同就没办法了,这种只能在服务端做下中转,把这俩个域名统一成同一个。

上面说的不是 ajax 请求,ajax 请求有额外的机制:

ajax 请求跨域的时候是不会挟带 cookie 的,除非手动设置 withCredentials 为 true 才可以。

而且也要求后端代码设置了对应的 header:

Access-Control-Allow-Origin: "当前域名";
Access-Control-Allow-Credentials: true

这里的 allow origin 设置 * 都不行,必须指定具体的域名才能接收跨域 cookie。
这是 session + cookie 方式的第三个坑,解决方案如下:

  1. 将Cookie的SameSite值设为None,Secure值改为true,并且升级为https,我们就可以跨域使用Cookie。
  2. 将Cookie的SameSite值设为Lax/Strict,并且将前后端部署在同一台服务器下,我们就可以在同一站点使用Cookie。

来总结一下session+cookie这种方案:

session + cookie 的给 http 添加状态的方案是服务端保存 session 数据,然后把 id 放入 cookie 返回,cookie 是自动携带的,每个请求可以通过 cookie 里的 id 查找到对应的 session,从而实现请求的标识。这种方案能实现需求,但是有 CSRF、分布式 session、跨域等问题,不过都是有解决方案的。

session + cookie 的方案确实不太完美,我们再来看另一种方式怎么样:


客户端存储的token

session + cookie 的方案是把状态数据保存在服务端,再把 id 保存在 cookie 里来实现的。

既然这样的方案有那么多的问题,那我反其道而行之,不把状态保存在服务端了,直接全部放在请求里,也不放在 cookie 里了,而是放在 header 里,这样是不是就能解决那一堆问题了呢?

token 的方案常用 json 格式来保存,叫做 json web token,简称 JWT。

JWT 是保存在 request header 里的一段字符串(比如用 header 名可以叫 authorization),它分为三部分:

如图 JWT 是由 header、payload、verify signature 三部分组成的:

header 部分保存当前的加密算法,payload 部分是具体存储的数据,verify signature 部分是把 header 和 payload 还有 salt 做一次加密之后生成的。(salt,盐,就是一段任意的字符串,增加随机性)

这三部分会分别做 Base64,然后连在一起就是 JWT 的 header,放到某个 header 比如 authorization 中:

authorization: Bearer xxxxx.xxxxx.xxxx

请求的时候把这个 header 带上,服务端就可以解析出对应的 header、payload、verify signature 这三部分,然后根据 header 里的算法也对 header、payload 加上 salt 做一次加密,如果得出的结果和 verify signature 一样,就接受这个 token。

把状态数据都保存在 payload 部分,这样就实现了有状态的 http:

而且这种方式是没有 session + cookie 那些问题的,我们分别来看一下:

CSRF:因为不是通过自动带的 cookie 来关联服务端的 session 保存的状态,所以没有 CSRF 问题。

分布式 session: 因为状态不是保存在服务端,所以无论访问哪台服务器都行,只要能从 token 里解析出状态数据就行。

跨域:因为不是 cookie 那一套,自然也没有跨域的限制,只要手动带上 JWT 的 header 就行。

看起来这种方式好像很完美?

其实也不是,JWT 有 JWT 的问题:

安全性
因为 JWT 把数据直接 Base64 之后就放在了 header 里,那别人就可以轻易从中拿到状态数据,比如用户名等敏感信息,也能根据这个 JWT 去伪造请求。

所以 JWT 要搭配 https 来用,让别人拿不到 header。


性能:
JWT 把状态数据都保存在了 header 里,每次请求都会带上,比起只保存个 id 的 cookie 来说,请求的内容变多了,性能也会差一些。

所以 JWT 里也不要保存太多数据。


没法让 JWT 失效:
session 因为是存在服务端的,那我们就可以随时让它失效,而 JWT 不是,因为是保存在客户端,那我们是没法手动让他失效的。

比如踢人、退出登录、改完密码下线这种功能就没法实现。

但也可以配合 redis 来解决,记录下每个 token 对应的生效状态,每次先去 redis 查下 jwt 是否是可用的,这样就可以让 jwt 失效。

所以说,JWT 的方案虽然解决了很多 session + cookie 的问题,但也不完美。

小结下:

JWT 的方案是把状态数据保存在 header 里,每次请求需要手动携带,没有 session + cookie 方案的 CSRF、分布式、跨域的问题,但是也有安全性、性能、没法控制等问题。

标签:web,请求,Session,JWT,header,session,cookie,服务端
From: https://www.cnblogs.com/sunyan97/p/17864819.html

相关文章

  • 存储机制(Window.sessionStorage 和 Window.locaStorage)
    <!DOCTYPEhtml><html><head><metacharset="utf-8"><title>webStorage</title><!--1.存储内容大小一般支持5MB左右(不同浏览器可能不一样)2.浏览器通过Window.sessionStorage和Window.locaStorage属性来实现本地存储机制3.相关API:1.XXXXXStorage.setItem('......
  • 【Docker】OpenWebRX Plus版本安装
    OpenWebRX是一个国外开源项目,基于Python语言编写,配合SDR设备使用,支持后台解码各种数字信号,将SDR接收软件Web化,通过网络实现多用户远程访问,功能非常强大。目前OpenWebRX版本已经到1.2了,但不知什么原因项目停更了,而后又衍生出一个OpenWebRX+分支,博主近日对这个分支版本做了测试,发现......
  • Web_XCTF_WriteUp | Training-WWW-Robots
    题目分析标题大致翻译:训练WWW网络爬虫。场景内部文段大致翻译:在这个小小的训练挑战中,您将学习Robots_exclusion_standard(网络爬虫排除标准)。robots.txt文件用于网络爬虫检查它们是否被允许抓取和索引您的网站或仅部分网站。有时,这些文件揭示了目录结构,而不是保护内......
  • 基于kore 的共享模块以及include 配置实现动态的web api 能力
    kore支持include以及动态load共享模块的能力,可以让我们实现动态扩展的api加载能力参考玩法参考示例项目结构├──conf│├──hello.conf│├──index.conf│├──mydemo.conf│└──myhello.conf├──hello.so└─......
  • IIS的web.config中跨域访问设置方法
    需求:页面要显示1个图片,但是因为各种原因,导致图片在服务器2上,但是要展示的程序在服务器1的上面,这样就造成了在显示的时候出现了跨域的问题,本来的思路为直接写个程序进行后台获得图片的路径,然后把图片进行下载出来,然后返回服务器1的图片地址,但是,由于这个周期不确定性和现阶段项目的......
  • ISCTF WEB
    圣杯战争!!!前置知识:反序列化魔法函数:(以俩个下划线开头的方法称为魔法函数)__construct()   在创建对象时候初始化对象,一般用于对变量赋初值。创建一个新的类时,自动调用该方法__destruct()   和构造函数相反,当对象所在函数调用完毕后执行.即当一个类被销毁时自动调用......
  • WebAssembly的应用
    概念和作用阿里云原生网关MSE上的插件,都是采集WebAssembly来执行的,你可以通过js,go来开发wasm文件,放到WebAssembly去执行。WebAssembly(简称Wasm)是一种用于浏览器和服务器端的低级虚拟机,它的作用在生产中具有广泛的应用:高性能计算:WebAssembly是一种高性能的虚拟机,可以用于执行密集......
  • Technical support website(URL)
    Thissoftwarerespectsandprotectsthepersonalprivacyofallusersusingtheservice.Inordertoprovideyouwithmoreaccurateandpersonalizedservices,thissoftwarewilluseanddiscloseyourpersonalinformationinaccordancewiththeprovisions......
  • wasm-vips libvips webassembly 实现
    wasm-vips是利用了emscripten将libvips编译为webassembly可以实现在node以及浏览器中使用libvips强大的图片处理处理以下是一个简单的试用参考试用app.js constVips=require('wasm-vips');asyncfunctioninit(){constvips=awaitVips();vips.Image.ne......
  • 亚马逊云科技基于 Polygon 推出首款 Amazon Managed Blockchain Access,助 Web3 开发人
     2023年11月26日,亚马逊(Amazon)旗下AmazonWebServices(Amazon)在其官方博客上宣布,AmazonManagedBlockchain(AMB)Access已支持PolygonProof-of-Stake(POS)网络,并将满足各种场景的需求,包括需要以高可用方式频繁访问PolygonJSON-RPCAPI的场景以及需要间歇性、不......