从原理上讲,登录很简单,就是输入账号密码和后台的数据库进行匹配,匹配上了就表示登录了,否则没有登录。这里主要总结的问题,用户登录之后,服务器端怎么确定你登录了,认定身份这个问题。
在刚学会编程人的验证里面,用户+密码登录后,直接返回一个标记islogin=1,这样就表示用户登录了,然后将islogin储存到cookie里面,直接读取cookie,如果直接读取到了cookie里面的字段,则用户登录,否则用户就没有登录。匪夷所思的确认登录的方法,确实在之前的一套源码里面出现过。居然使用cookie来识别用户是否登录到进入了后台,如果登录,就继续走真正登录了的逻辑。对于使用cookie识别用户登录的方法,直接导致admin的登录是摆设,只要将cookie里面的登录uid改成1(也就是管理员) islogin =1 这样就表示用户管理员登录了。
这里涉及到一个对cookie很浅显的概念,Cookie是一种小型的文本文件,由网站创建并存储在用户的计算机或移动设备上。当用户访问网站时,网站的服务器会发送Cookie到用户的浏览器,浏览器随后会将Cookie保存在本地。这样,每当用户再次访问该网站时,浏览器都会将保存的Cookie发送回网站,使得网站能够识别用户并记住用户的浏览历史、偏好设置等信息。也就是cookie是登陆者存档在本地的信息,是可以被本地用户进行更改的。显然登录不能只依靠客户端的cookie来识别登录,极少数情况下可以使用,比如自己一个人使用的系统,懒得每次都登陆,直接使用cookie里面的存储值。
大部分的登录,依赖的是客户端一个cookie,服务器端一个session,每次请求,服务器端都是获取该cookie字段进行检测。可以拿一个前面基础的fastadmin网站作为对比,一般php网站有个phpseed参数,复制一个登录账号的phpseed到另外一个浏览器,然后复制之前的登录的URL,可以神奇的发现,该网站在另一个浏览器里面也登录了,第一次实现这个效果的时候,感觉到非常吃惊。其实原理很简单,因为服务器端基本只会验证这个PHPSESSID,你的代码里面没有验证服务器/来源/上下文之类的,依靠PHPSESSID的值进行唯一性认证,自然会将你当成登录了看待。也就是说,绝大部分的小网站,已经可以依赖PHPSESSID来识别用户是否已经登录,这个唯一标志是服务器和客户端每次建立连接的时候,返回给客户端的。
正是基于这个特点,如果一个人想登录你的后台,只要获取到了你的PHPSESSID即可。但是PHPSEEID认证有个巨大的缺陷,它在服务器端是有生存周期的,本质其实是服务器保存了一份自己的COOKIE(我们称之为session机制),包括不限于服务器需要紧急重启导致登录失效(很多游戏平台,每次更新服务器都需要你重新登录就是因为其保存的会话session丢失,需要你重新登录建立一次新链接),又或者到了生命周期(由脚本代码的配置决定)又或者客户端关闭了网站(一般关闭网站,会直接导致PHPSESSID被删除),这个时候,你复制出去的session是无效的,因为已经失效了。更不用说,前后端是分离的,对后端的每次请求,都不可能带着一个这样不可控的参数。
在这种情况下,推出了token的概念,token是一个类似phpsessid的一种升级的解决方式,我们只需要用一种对称加密方法(也就是我们自己可以通过我们的key进行解密,其他人在不知道key的情况下,理论上无法解密信息)。用token来鉴权,最少有三个很明显的好处——
第一,密文有意义,可以储存类似用户uid之类的关键信息
第二,不必在于用户是否关闭了浏览器,服务器是不是重启了,甚至不用在乎到底是哪台服务器,只要接收了该token,并能解密,我们服务器就可以继续为该客户端服务
第三 方便代码层面管理控制,依赖脚本底层机制管理我们并不知道其是否能按照我们的设想运行,但是加密解密是我们自己代码控制的,一定是可以随时让其失效。
于是很快,使用token加密的方式明显铺开。这个时候,我们只需要解决怎么进行对称加密的难题即可。所幸,每个语言都有这种语言加密函数库,加密的算法比较复杂,我们不用深究,只需要简单引入即可使用。例如PHP里面的
openssl_decrypt($data, 'AES-128-ECB', $key, 0); 加密数据,加密方法,加密的key,位移 解密openssl_encrypt($data, 'AES-128-ECB', $key, 0); PYTHON里面的from cryptography.fernet import Fernet 库也可以类似效果。
也就是我们将一个字符串进行加密运算之后,丢到服务器端,并设置其为我们的token,然后规定用户每次需要进行操作的时候,都必须带token参数,可以cookie携带,也可以header携带,或者直接字段里面发送,服务器端拿到token之后,根据自有的key进行解密,最后还原出加密的字符串,同时我们可能储存了对应的uid信息在token里面,这样我们甚至无需用户端再次给我们发送uid这个参数,就已经能识别用户身份。很多登录后,进行的操作,都是依赖token对身份的唯一性操作,都是依赖传递的token,只是很多传递方式比较隐蔽。
小结:单一cookie验证身份不可靠,只依赖服务器端的session识别身份会让用户关闭浏览器后,无法识别用户身份,也会让分布式部署的服务器无法识别用户身份,所以用token鉴权优势明显。