首先考虑几个问题
问题一 http协议是无状态的,那么大多数网站是如何记住用户身份的?
问题二 类似于第一个问题,但又略微有些不同,基于http协议的app应用又是如何记录用户身份的?
问题三 如何保持自动登录状态?
其实,做过相关开发的同学很快就能说出很多,你们说的都对。问题一,通过session和cookie。问题二,可以有很多种方式,较为常用的可能是app本地存储+服务端缓存。问题三,同问题二。
所以,问题来了,目前这样的方式到底合不合理,到底安不安全?!!
答案总是那么令人沮丧,但是又是非常现实。
不安全,不安全,不安全!
事实上,黑客总有10000种方式来利用我们的系统的安全漏洞,我们能做的就是尽量减少安全漏洞。然而,当我们的系统前端完全暴露给黑客的时候,我们很多的安全工作只能尽量往后端转移,特别是身份认证相关内容。
数字签名的应用
这里我们不考虑黑客进行中间人攻击,我们主要关心的是如何利用我们现有的资源(包括各种加密方法,http协议等)设计一个可以首先确保正常身份认证功能的并且可以有效防止存储在前端的信息被篡改的方式。
通常首次用户身份验证是通过用户输入用户名密码或者通过OAuth2协议(如微信登录等)来实现的,这里我们在服务端判断用户登录成功后,首先会在服务端缓存用户信息,用于之后的身份验证,而又会给前端返回一个信息,在之后前端需要验证身份的时候,传入相应的信息给服务端,服务端会去根据该信息搜索缓存,找到了即为用户为登录状态且身份未过期,未找到需要重新走一遍登录流程。事实上,问题一、二、三种基本都是这么做的,不同的是,问题一是利用了http的cookie和session,在cookie中存储了session信息,从而找到相应的session也就找到了用户信息。但是这样会有黑客在前端故意存储别人的信息,从而可以冒用别人的身份,特别在前端存储信息特别有规律的情况下,如为用户的数据库id数字,或者用户名等。
所以这里就开始说到主角了,数字签名,有些时候为了方便,可能直接在前端存储用户id作为身份认证资料,这个其实可以理解。但是这很容易进行伪造(事实上,随便猜一个数字就可以猜到某个用户的id或者用程序根据字典去暴力跑)。所以,在便利的情况下,在前端不能简简单单只存一个信息,还要存储一个数字签名,这个签名由用户登录成功后服务器返回(通常通过一系列加密算法,为不可逆)。在之后前端需要根据该信息向服务端请求用户身份信息时(不考虑expire等内容),首先将前端传来的身份认证资料(如上述的用户id)再用相同算法进行加密一遍,和传来的数字签名进行比对,比对成功后再进行其他相关操作。