WEB验证jwt session cookie之间的关系

发布时间:2021-06-24 09:52:35 作者:chen
来源:亿速云 阅读:237

这篇文章主要讲解了“WEB验证jwt session cookie之间的关系”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“WEB验证jwt session cookie之间的关系”吧!

Web认证是任何一个认真一点的网站都必须实现的基本功能。这个功能解决了让服务器“认识你就是你“的问题。这个功能看起来貌似很简单,但是实际上处处是坑。因为认证是依靠一套技术整体运作才能完成,所以仅仅是把一些现成的技术简单拼起来是不够的。你必须了解每一种技术能做什么,不能做什么,解决了哪些问题,才能精心设计一套认证功能。

两种认证

目前市面上能见到的认证方式分为两大种——基于Session的和基于Token的。

所谓基于Session的认证,是指在客户端存储一个Session Id。认证时,请求携带Session Id,并由服务器从Session数据存储中找到对应的Session。这种方式在很多网站框架下都有

所谓基于Token的认证,是指将所有认证相关的信息在服务器端编码成一个Token,并由服务器签名,以确保不被篡改。Token本身是明文的。存在Token里的信息可以有比如user id、权限列表、用户昵称一类的。这样服务器只要拿着token和token的签名,就可以直接验证用户的身份是合法的。在现实当中,基于Token的认证的主要标准是Json Web Token (JWT),见RFC 7519。

WEB验证jwt session cookie之间的关系

认证方式

但是我不得不说的是,基于Token的认证在现实当中并不是很实用……

JWT

一个JWT大概长这样:

base64(header).base64(json payload).signature

通过这样的机制,JWT中可以存储一些认证必要的信息。给定一个JWT,服务器只要验证:

之后服务器就可以信任这个JWT中包含的信息,包括user id、包含的权限等等。服务器不需要自己再去查询一遍这个用户的信息,以及这个用户的权限信息,就可以对请求作出相应。不用session了,无状态大法好!然而,需要泼一下冷水的是:

这两个严重的缺陷限定了JWT只能用到一些不太认真的场景。而对于真正的社交、金融、游戏等认真一点的服务,还是要选择基于Session的认证。

当然,token中的签名还是有好处的,签名可以确保token的确是服务器产生的,不会被篡改。如果token中包含了user id,那么还可以实现简单的前端错误上报;如果token中还有session id,就可以在服务器端实现基于Session的认证。因此,你可以将user id、session id、token过期时间等几个关键数据放到payload里——只放这几个,不放其他的数据,得到一个用来做Session认证的JWT。更进一步,如果你把JWT的规范稍微小改一下,比如payload不用JSON,而是更紧凑的格式;定死了签名算法,即可省略JWT的header了;最后再优化一下编码格式,就能得到一个你自己的token。

但,无论用session还是token,还是什么其他的名字,这些都不重要。重要的是服务器这边必须实现session机制,以便于对用户登录信息进行有效的管理。

有人告诉过我一个使用基于Token + 无状态的认证方式的原因:他们的存储是一个云服务,并且按照调用次数收费。所以他们让用户每次将Token传给服务器,就是希望尽量少的调用那个云服务。对此我表示很无语……

怎么存储认证信息

谈完了session和token,我们来说所说这个信息在客户端怎么存储。客户算也分两大类——浏览器和Native App。先说说浏览器。

浏览器

浏览器中的存储主要是Local Storage和Cookie。

其实浏览器用于存放认证信息的存储还有Session Storage,但是它和Local Storage差不多,只是失效的机制不太一样。这里只用Local Storage讨论。

使用基于Token认证的开发人员很喜欢使用Header + Local Storage。因为这样可以有效防止CSRF (下一小节专门讲)。

但是使用Local Storage,反而会增加中招XSS(Crossing Site Script)的机会。一旦中招XSS,攻击者可以轻易的拿到认证信息,并且传回自己的接受网址而不被用户察觉。这样一来攻击者能够轻易的代替用户登录了。

整个浏览器中,只有一种资源是脚本无法访问到的。这就是被设置为HttpOnly的cookie。这是非常理想的放置认证token/session id的地方。设置这种token只需要在Set Cookie时这么写:

Set-Cookie: access_token=xxxxxxxxxxxxxxxxxx; HttpOnly; Secure; Same-Site=strict; Path=/;

(Secure和Same-Site是什么?下文会解释)

XSS攻击者没有任何办法从HttpOnly的Cookie中拿到你的认证信息,除非他能在你登录网站后,直接进入你的电脑,打开浏览器的开发者工具并人肉复制粘贴(叫你不锁屏,哼)。

有些人坚称自己的程序可以保证不受XSS的攻击,所以可以放心的用Local Storage。比如使用React框架开发的程序理论上所有的DOM节点都由React的虚拟DOM产生,所有的标签生成都进行了escape。espace掉的脚本就无法执行,也就不可能XSS了。

这样讲没有错误,但是XSS最令人头疼的地方在于你很难保证你的网站对所有用户的输入都进行了escape。

只要有一个漏洞存在,那么整个防护体系就完全失效。这就是为什么HttpOnly Cookie这样的绝对隔离措施很关键的原因。

Native App

Native App比浏览器相对简单。一般Native App都是静态编译产生,不存在XSS的问题。同时移动操作系统都会有沙箱机制,避免其他App读取到自己的数据(除非你root了……)。因此,Native App可以比较放心的将数据存在App沙箱内某个存储即可。如果不放心,可以考虑如iOS KeyChain或者Android KeyStore这样的设施。

但Native App与服务器交互有一些区别。Native App一般是不直接支持Cookie机制的。所以如果一个服务器端使用Cookie来保存认证信息,就需要Natvie App手工解析Set-Cookie Header,同时,Native App因为不直接支持Cookie,所以倾向于在请求中使用AuthorizationHeader来传入认证信息。这也需要服务器适配。当然,最简单的办法是让Native App引入一个模拟Cookie行为的库。

防止CSRF

CSRF代表Crossing Site Recource Forge。大致的触发流程是:

  1. 用户登录了站点A,并且在Cookie中留下了A站点的认证信息

  2. 用户进入了站点B,而站点B用一些方式(比如一个提交行为是到A站点某关键接口的表单)引诱用户去点击。当用户点击时,会发出到A站点的请求。而浏览器会给这个请求附带上A站点的认证信息,从而让这个请求能够执行。这种行为可能是,但不限于,给某个A站点的某个其他用户提权/转账/发文辱骂等等。

上文中提到了,很多人用JWT+Local Storage的本心是为了防护CRSF。这样做的原因是——因为Cookie的发送是完全由浏览器控制的,不受网页本身的控制。所以最简单直接的办法,就是不用Cookie,不让自动发送认证信息成为可能。问题在于,这么干是有XSS风险的。从上文中可以看到,为了避免XSS,就必须用HttpOnlyCookie。

那么怎么在使用Cookie的同时,还能防范CSRF呢?

传统页面Web网站

在传统页面Web网站中,一般会使用CSRF Token。这是个非常流行的做法。像Tomcat这类的容器都会自带CSRF Token的产生和检查Filter。

CSRF Token是这样工作的。客户端要首先向服务器请求一个带有提交表单的页面,服务器返回的页面中会嵌入一个CSRF Token。当用户提交表单时,CSRF Token会被一起携带发给服务器做验证。所以当服务器看到CSRF Token,就可以放心大胆的确认用户的的确确是看看到了提交前的表单界面,从而避免了用户稀里糊涂提交一个被伪造的表单的可能性。

SPA

CSRF Token只适合于传统的页面请求,在SPA的情况下会比较尴尬。

在SPA中,客户端与服务器之间的交互主要是通过接口完成的,没有页面的概念。此时,你的确可以照猫画虎的做一个接口让用户拿到CSRF Token,但这样什么也确认不了。因为攻击者可以调用同样的接口,拿到合法的CSRF Token。

这时有几种办法:

总是使用https

大学上网络课时,老师讲解了http的一些原理,然后给我们留了个作业——去外边提供WIFI的餐厅用嗅探器扒别人的密码。两周后,我们做完了作业,心情是悲催的——尼玛互联网都发明了十几年了,连最基本的防护都没有……

http是明文传输的。在http下,用户输入的任何信息,从他的电脑到服务器之间的每个链路节点都是明文的。在这里个链路中的任何地方,都可以截取到完整的数据,包含你的密码,认证token……

这就是为什么https是必须的。https主要提供三个保证:

早些时候,很多人对https有一些抵触,大致的原因是,支持https需要软件改造;服务器对证书进行密码学运算要耗费很多CPU;同时也会带来跟多的网络请求和响应(多了ssl握手)。这无疑会带来一些成本和体验上的问题。但那已经是10多年前的事情了。现在的软硬件处理能力和网络基础设施比起10年前都有数倍的提高。如果今天,一个商业网站仍然坚持不用https,那么可以请他的老板去大街上裸奔。

使用了https后,为了进一步保证安全,将Cookie设置为Secure。这样,浏览器就可以只在访问https网址时才会携带Cookie。如果不做这样的设置,通过https站点设置的Cookie,仍然会向http站点发送。当这个站点的域名解析被劫持,就可能造成向一个伪造的服务器发出你的认证信息。

认证信息不应该永久有效

很多人为了“用户体验”,选择让一个登录永久有效。这样做是非常危险的。因为一旦用户的认证信息被别人获取了,就永久性的失去了防御的机会(记得上面说的不锁电脑屏幕的后果吗?)。

因此,总是要保证认证信息的有效期是有限的。一般根据业务场景的安全级别不同,可以设为若干分钟~若干天。就算是社交娱乐类的应用,有效期最好也不要超过两周。

但,为了让频繁使用的用户体验更好,可以考虑实现会话期续期。但需要注意,这里说的续期是指从用户角度看可以延续其不需要登录的时间长度,而不是直接让session/token有效期变长。必须实现为给用户替换一个新的session id/token。这样做,既能保证同一个认证信息不会永久有效,又能让正常的、频繁使用的用户免除登录之苦。

总结一下

总结下来,一个靠谱的Web认证应该:

感谢各位的阅读,以上就是“WEB验证jwt session cookie之间的关系”的内容了,经过本文的学习后,相信大家对WEB验证jwt session cookie之间的关系这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

推荐阅读:
  1. Angular之jwt令牌身份验证的实现
  2. express框架中使用jwt实现验证的方法

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

jwt session cookie

上一篇:Spock测试框架的介绍和用法

下一篇:Collectio集合中的线程安全问题有哪些

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》