access怎么做批注_你还在纠结怎么使用Cookie+Session还是JWT吗?

6c3d9adc771dc3b191e093f0cd22c4d5.gif

Cookie+Session还是JWT呢?

6130999bf622e98f559f176d3e157fa8.png

最近做了一下调研,在纠结这个新项目要用 jwt 呢?还是采用session+cookie这种形式呢?

顺便好好记录下他们的特点,还有一些要面对的问题? 有什么不对的欢迎指正!! 谢谢!?

a9404cc9713c1c301e86b89f34a13c06.gif

Cookie,Session,Token(JWT)    Cookie        特点:        属性表        例子            set-cookie:            过期时间:    Session        特点:        问题:    Token        特点:        问题:            (一) 怎么让token无效?            (二)为什么需要一个新的refresh-token呢?            (三) 使用 refresh token 时的并发问题?

1.Cookie

  特点:
  1. 存储在浏览器中,一般情况下每次请求都会带上这个cookie

  2. cookie 无法跨域  (跨域涉及到 浏览器的同源策略 (协议,端口,域名))

  3. cookie 最大是 4kb

  4. 浏览器一般允许存放 300 个Cookie,一个站点最多存 20 个Cookie

  属性表:
属性                                       必填       说明
name=valuecookie的 名称和值
Expires=datecookie 的过期时间  客户端和服务端的时间不同步的话会有问题
Max-Age=numbercookie的存活时间  number是一个数字,时间单位是秒0或者负数会让 cookie 立刻过期 ExpiresMax-Age 这两个同时设置时,Max-Age 会生效,因为它优先级比较高
Domain=valuecookie 所属的域名
Path=value只有当路径匹配时才会带上该 cookie ,匹配时也会匹配子目录 如:/aa  则 /aa/bb 也会被匹配到
Secure表示该 cookie 只在https中有效 ,有助于减少 中间人 攻击
HttpOnly禁止 JavaScript 访问 cookie,有助于防范 XSS(Cross Site Scripting) 攻击,跨域脚本攻击
SameSite=value

1. Strict  最严格的模式,当当前网页的 URL 与请求目标的 URL 一样时,才会带上 cookie(注意iframe!)

2.Lax ( 默认 )  像加载图片和frames就不会发送了,但是在用户点击a标签链接时会发出 

 3.None  设置该选项必须带上 Secure 属性!防止 CSRF (cross-site request forgery) 攻击

具体可以看看 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie

  例子:

1

set-cookie:

可以在 浏览器 的 response header 中 看到类似下面的参数:

set-cookie:  

dwf_sg_task_completion=False; Domain=developer.mozilla.org; expires=Sat, 09 Jan 2021 06:53:31 GMT; Max-Age=2592000; Path=/; Secure

2

过期时间:

如果没有设置这个过期时间的话,这个cookie就会随着浏览器的关闭而消失 。在浏览器的控制台中表示为 session

ba1c12b352f3615a540a19b94d2f6d72.png

4bb028a4a89aecb3bda1fbf7294f6034.gif

2.Session

   特点:
  1. 存储在服务器端

  2. 每次访问都会刷新它的有效时间

  问题:

由于session存储在服务器,所以我们要考虑到服务器的压力问题,当在线人数多的时候,session所占用的服务器资源肯定会比较多,此时单个服务器的压力是比较大的,我们可以考虑做个集群,减轻单个服务器的压力。

接着就得考虑下这个session的共享问题了,怎么在多个不同的服务器上共享这个session呢?

这里也有多种不同的解决方案,比如:

  1. 使用 Spring session 来解决这个共享问题

  2. 使用 nginx 的 负载均衡机制中的 ip_hash 模式  ,将对应的 ip 路由到指定的服务器上

  3. 使用redis 存储 session

  4. tomcat 集群的 session 复制

4bb028a4a89aecb3bda1fbf7294f6034.gif

3.JWT

jwt 可以看看博主之前的这篇文章 从 JWT 到 JWS 到 JJWT?

  特点:
  1. 服务端实现无状态化

  2. 记录用户的信息,避免多次查询数据库

  3. 存储在客户端

  4. 能够避开同源策略,不用考虑跨域问题

  5. 因为不用cookie了,也可以避开 CSRF 攻击

问题:

1

怎么让token无效?

这个问题的实际场景有如下:

怎么解决用户注销问题?

9db35460c1ec8721ac6195aef549b88e.png e70962e26344d7e60a0a3ac2664cf59d.png

用户改密码了怎么办?

由于服务端的无状态化,不能很好地控制这个token,所以我们可以考虑让它变成有状态的。

虽然JWT是无状态的,但是有些场景session+cookie也不好用,特别是现在这么多app呀,小程序等各种各样的移动场景,还有服务端分布式的盛行,使用jwt的优势还是比较明显的?,所以还是不去纠结这个jwt怎么像session了?

哈哈哈 毕竟这里使用的方式也是类似spring-session那样的机制。

可以在服务端的redis中记录这个token,直接将用户id和对应的token存到redis中,并设置过期时间,当用户修改密码或者注销登录时删掉该token,这样当用户操作其他功能时,在redis中找不到对应的token,就判定该token无效。

6cf01a6f48de6428de44935783b02157.png

redis 命令如下:

  1. 创建时:setex uuid 1800 token

  2. 删除时:  del uuid

这样做也可以应对用户在多端登录的情况,如:在PC登录和在手机登录,如果在redis中已经有这个token了,就直接返回对应的token就好了。

接着我们要解决第二个问题了?

3926a616ded2775413741b94ddb7adbc.gif

2

为什么需要一个新的refresh-token呢?

用过 Oauth2 协议 的小伙伴们肯定熟悉, 上面的那个token 我们称之为 access-token ,同时呢 , 我们也需要一个 refresh-token , 来获取新的token

d573b1fca2028026c0b46934d1ac2242.png

眯着眼猜测肯定是因为安全啦 哈哈哈 ,博主的简单猜测:因为你的access-token 每次请求都会带上,万一你发的请求被拦截到了?,别人就可以拿着你的token去干坏事了,但是这个  access-token 的有效时间一般是比较短的,而且不能 续期 ,所以这也间接地提高了系统的安全性。

当这个   access-token  过期时, 我们就通过这个 refresh-token去获取新的   access-token  ,以避免频繁地让用户重新登录。

当然我们可以看项目的实际使用再决定需不需要使用  Oauth2 ?。

如果只是登录自己的服务器,不用第三方认证授权的,我们可以自定义这个jwt?,只是在定义时多定义一个 refresh-token,但是这个 refresh-token只能用来获取新的 access-token , 不能做其他的, 同时它的过期时间也比较长,? refresh-token 一般是30天。

观察微信后发现,如果你的账号在别的手机设别上登录,则你需要再重新登录才可以继续在自己的手机上使用,所以我们也可以在jwt中记录下手机设备的唯一值?,用来鉴别用户是否需要重新登录,同时也可以根据业务需求去定义这个 refresh-token 是否需要续期,是的话多久更新一次等等细节

接着就有了第三个问题了?

3926a616ded2775413741b94ddb7adbc.gif

3

使用 refresh token 时的并发问题

额 这个问题感觉比较复杂,毕竟涉及到并发,可以考虑加锁呀。

当这个  access-token  过期时,后端将返回一个特定的状态码告诉前端说这个token过期了,需要重新刷新?。而前端此时因为异步的原因,导致同时发了好几个 刷新token的 请求到达后端,这时就出现了这个并发的问题了。

解决方案:

后端:重新生成新的  refresh-token ,同时替换掉该用户对应的  refresh-token 和 access-token。利用 redis锁机制,如 SETNX, 将这个旧的  refresh-token  和 新生成的  access-token 放到一起,并设置过期时间如3s,这样3s内刷新token的请求都会拿到同个新生成的  access-token,则3s后用户面发送过来的   refresh-token  会无效

后端:不重新生成  refresh-token  , 也是利用 redis锁机制,如 SETNX,   直接 将  refresh-token 和 新生成的 access-token 对应起来,并设置过期时间如3s,3s内直接返回该 access-token ,同时替换掉该用户对应的 access-token,3s后可继续重新生成

前端:暴力点就直接在 access-token 快过期的前几分钟去调用一次刷新 token的接口。

前端:温和点的话,就设置延迟处理,记录下上个刷新token的时间,如果时间太短的话就不发出去?

谢谢可爱又帅气的大佬们的观看!祝您 天天开心!?  

感谢您的关注!您的每个关注,都是博主生发的动力 ?

126e0680a078d3d3823d18d0b75549fb.png         

点个“在看”表示朕

已阅

往期精彩回顾

38429d91199c2a06de25fcc59eb494c2.png

序列化单例模式的实现————readResolve 源码解读

f168143d636bd8779a2c4594aa02fa69.png

单例模式八个例子

123df6a1f5f16904d8f256b7e067ecf9.png

java8四大函数式接口

cc978455797cff2f85c5e69a1c7c294c.png

jackson解析泛型的正确写法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值