29 Session与Cookie:账户体系的安全设计原理 你好,我是王昊天。

我有次在访问某个页面时,为了下载一些东西,按照页面要求进行了复杂的登录操作。之后我不小心关闭了当前页面,然后再一次点开这个页面,麻木的准备再来一遍复杂的登录操作时,我神奇地发现,面前的Web应用竟然是登录成功的状态,你知道这是怎么一回事吗?

事实上,这个现象是由Web账户体系的安全设计所导致的。在这一讲中,我们将会对它进行学习,这样你就能清楚地知道问题的答案啦。下面我们就正式开始今天的学习。

现在几乎每个大型Web应用都会存在账户体系,当我们需要获取Web应用中的某些服务时,Web应用会首先对我们的身份进行认证。所以接下来,我们会从身份认证的相关基础知识入手。

身份认证

身份认证的方式有多种,我们可以用最典型的账号密码进行认证,除此之外,我们还可以用cookie(session)、Token、数字证书以及手机验证码来验证。这里你可能对于cookie以及Token会比较陌生,不过不用担心,我们会在后面对它们进行详细的讲解。

图片

在这些认证过程中,可以分为两种类型,即登录过程的认证以及保持登录的认证

为了让你更好地理解它们二者之间的区别,我们一起来看一个示例。

图片

这是谜团(mituan.zone)的登录页面,我们需要输入正确的用户名、密码以及验证码才能通过身份认证,很明显这是登录过程的认证。

当我们登录成功后,我们会发现浏览器中多了一些cookie信息。

图片

这些cookie信息有一定的有效期。在有效期内,cookie信息会一直存在,它使得我们下次访问这个页面时,无需再次输入账号密码进行登录,而是可以直接用cookie信息来实现身份认证操作,这就是保持登录的认证。

你现在知道导入中神奇现象发生的原因了吗?其实在导入部分中的自动登录,就是通过保持登录的认证来实现的。而这种认证方式,主要是通过会话管理来实现的,接下来让我们简单了解下会话管理的作用。

会话管理

在学习会话管理之前,我们首先需要巩固下HTTP协议的知识。

HTTP协议是无状态无连接的协议,服务端对于客户端每次发送的请求都认为它是一个新的请求,上一次会话和下一次会话是没有联系的。因为它无法保存登录状态,所以从协议本身来说,它不适合用来做会话管理。

因此,我们会使用一个上层应用去实现我们的会话管理功能。这个应用可以在切换页面时保持登录状态,并且对用户是透明的,这样就使得我们能在短时间内再次访问一个登录过的页面,就会保持登录状态。

经过上述内容的学习,你已经知道了会话管理具有什么作用。接下来,让我们具体学习下会话管理的两种典型方式,即基于session的认证以及基于Token的认证。

基于 session 的认证

Web应用可以基于session的认证来实现保持登录,它的具体实现方式如下图所示:

图片

用户在首次访问Web应用时,会将自己的账号密码通过POST方式进行上传,然后Web应用服务器会对账号密码进行检查。如果检查通过就会给用户配置一个sessionid,并将它存储在服务器内存中,之后再把这个sessionid发送给用户。

注意这里sessionid的位置可能在URL、隐藏域以及cookie中。由于cookie信息较为隐蔽些,所以将sessionid放在cookie中相对来说更为安全,因此这一实现方式也最普遍。

用户在收到Web应用服务器的回应之后,再次对Web应用发起请求的cookie中就会自动包含sessionid信息。Web应用服务器会对其中的sessionid信息进行检查,以获取用户的登录信息,如果信息正确,就让用户处于登录成功的状态,否则需要重新进行登录过程的认证。

值得一提的是,为了安全考虑,Web应用通常会给sessionid设置一个过期时间,使得sessionid仅在某个时间段内有效,这样就可以有效地抵御攻击者盗用sessionid绕过身份认证的行为。

到这里,我们已经学习了Web应用是如何利用session进行身份认证的。而这里还有一个很重要的知识点我们有必要深入了解一下,那就是在session进行身份认证中存在的典型攻击方式——会话固定攻击

在之前的学习中,我们知道了sessionid可以存在于URL中。在这种情况下,如果登录前后sessionid不变化,那么攻击者就可以发起会话固定攻击。

这里我已经画出了会话固定攻击的示意图,让我们一起看看吧。

图片

攻击者首先访问一个需要登录的网站,获取到Web应用返回的sessionid信息。由于攻击者没有账户密码,所以只能通过发送一个诱骗信息给受害者,使得受害者用这个sessionid实现登录操作。这样攻击者的sessionid就通过了验证,使得攻击者再次用这个sessionid信息访问被攻击网站时,可以直接通过保持登录的认证。

这就是将sessionid信息放在URL中的安全隐患。

基于 Token 的认证

除了基于session的认证之外,Web应用还可以利用Token来实现会话管理。

基于Token的认证方式,如下图所示,让我们从图中观察它是如何实现的吧。

图片

用户首先需要通过POST方式上传账号密码信息,进行登录过程的认证,Web应用服务器接收到之后,会检查账号密码信息是否正确,如果正确就会生成一个包含密码信息的Token值,这里以JWT(JSON Web Token)为例。

之后服务器会将这个Token信息发送我们的浏览器,接着浏览器会将这个Token信息保存在Header中,使得以后每次请求的Header中都会包含这个Token信息。服务器在接收到Token信息后,会从中提取出用户的账户信息,并对此进行检测,然后将响应发送给我们的浏览器。

这就是基于Token的认证方式,下面让我们以JWT为例进行学习,深入地了解Token的具体形式。

图片

上方方框中的内容是一个完整的JWT信息,它可以根据.分割成三个部分,我们将它不同的部分用不同的颜色进行显示。接下来,让我们逐一分析JWT各个部分的内容。

第一个部分经过base64解码就变为了蓝色方框中的内容,其中alg的内容设置的是signature中签名使用的算法,而typ的内容则定义了这个Token的类型。

第二部分解码为绿色方框中的内容,它包含了用户相关的信息,Web应用可以根据这些信息来确定用户的身份。

最后一部分解码为橙色方框中的内容,它包含了对Token信息的完整性验证签名。其中需要用到仅有服务器知道的secret信息,这也是导致攻击者无法伪造Token信息的关键。

以上就是JWT的组成结构。其中Header以及payload用到的都是些通用数据,攻击者很容易就可以伪造出来。唯一有难度的就是对secret签名部分的伪造,事实上,攻击者可以通过密钥爆破的方式,尝试进行Signature信息的伪造。一旦伪造成功,攻击者就可以以任意身份登录这个Web应用,这对Web应用来说是极大的威胁。所以Token信息的设计者,需要有意识地提高secret的复杂度。

到这里,你已经学习了会话管理的两种典型方式。接下来,让我们拓宽视野,简单了解下单点登录的知识。

单点登录

如今的Web应用越来越多,同一个公司可能就会研发出多个Web应用,如果每个应用都需要分开登录注册,那既会使得用户感到不方便,也会增加开发成本。为了解决这个问题,大家通常会采取单点登录方案。

单点登录就是用户只需要登录一次就可以访问所有相互信任的应用系统。它把认证的流程统一起来,使得认证的风险集中化。

图片

这样,我们只需要在那统一的登录流程中做好安全认证措施,就可以实现对多个应用的身份认证。单点登录既能降低开发成本,也可以提高登录的安全性。

总结

这节课我们学习了账户体系的安全认证设计。

首先,我们学习了身份认证的方式,了解到除了我们熟悉的登录过程认证之外,还有保持登录认证这一种方式。

接着,我们深入学习了保持登录认证的方式,知道了它是由会话管理方法实现的。然后我们对基于session的会话管理以及基于Token的会话管理进行了全面的学习,我们不仅知道了它们保持登录认证的实现方式,还知道它们存在的安全隐患。

最后,我们了解了一个面对多个应用需要登录验证时的解决方案,即单点登录。使用单点登录既可以统一管理所有的登录认证,还可以降低多个Web应用的开发成本。

思考题

你知道在基于session的保持登录认证中,为什么将session信息放置在cookie中会更加安全吗?

欢迎在评论区留下你的思考。如果觉得今天的内容对你有所帮助的话,也欢迎你把课程分享给其他同事或朋友,我们共同学习进步!

参考资料

https://learn.lianglianglee.com/%e4%b8%93%e6%a0%8f/Web%e6%bc%8f%e6%b4%9e%e6%8c%96%e6%8e%98%e5%ae%9e%e6%88%98/29%20Session%e4%b8%8eCookie%ef%bc%9a%e8%b4%a6%e6%88%b7%e4%bd%93%e7%b3%bb%e7%9a%84%e5%ae%89%e5%85%a8%e8%ae%be%e8%ae%a1%e5%8e%9f%e7%90%86.md