HTTP是无状态的协议,它不会记录和保存之前连接的状态。那么它进行登录验证和授予客户端权限的过程是怎样的?我们经常使用微信、QQ等进行第三方的授权登录。又是怎样实现的?本文将通过介绍HTTP登录和授权机制帮助大家理解这些问题。
-
一、Cookie
Cookie在英语里是曲奇、小饼干的意思。它的作用是帮助服务器把用户数据存储在用户的客户端本地。通过它让HTTP无状态工作方式,变成“有状态“的方式。
1.1 Cookie起源
早期的浏览器公司会帮助用户进行网站的开发。当时的购物网站需要实现“购物车“的功能。盛极一时的Netscape(网景)公司的做法,是将购物数据存在客户端的本地,为此开发了一套完整的流程,就是Cookie。因此,Cookie开发出来就是用于实现”购物车“的功能。
后来我们知道,电商购物车功能都改为在服务器端实现。Cookie也失去它最初的作用,但是它完整的实现机制却被保留下来,用于用户登录状态管理、用户偏好管理、用户行为追踪等。
1.2 Cookie工作机制
看一下用Cooke早期用于实现“购物车“功能的工作过程:
1、用户发起请求在购物车增加一个“apple“;服务器收到并处理请求后,返回用户结果,并通过set-Cookie将“apple“加入”购物车“;用户将该Cookie存在用户本地,这里需要同时记录网站的信息和对应Cookie信息,避免访问多个网站发生错乱。
2、用户再次向服务器发起请求,这次将一个“banana“加入购物车。用户同时将当前记录该网站的Cookie同时发送过去;服务器收到请求并处理后,将新的带有一个”apple“和一个”banana“的Cookie通过”set-Coolie”返回给客户端;客户端收到返回后,更新本地的Cookie,即购物车。
3、用户向服务器发起结算请求,同时将本地的Cookie发送过去。服务器收到请求后,进行结算。完成后,服务器更新客户端Cookie,清空购物车。
以上购物车实现的简单流程,就是典型的Cookie工作机制。我们现在用的Cookie机制也是这样工作的。
1.3 Cookie作用
前面说到,Cookie已经失去了它最原始的作用。我们看一下现在Cookie在HTTP网络访问中的作用和实现原理。
1)、登录状态管理
它的原理就是利用Cooke保存登录数据在本地,每次客户端发起请求时,同时发送Cookie数据给服务器,服务器通过检查Cookie数据确认用户登录状态。将HTTP从无状态协议,改为有状态。
客户端向服务器发起登录请求,登录成功后,服务器将登录信息通过Cookie返回客户端,并在客户端保存起来。
客户端再次发起HTTP请求时,带入保存的该网站登录信息的Cookie数据。服务端收到请求后,解读Cookie,确认客户端是已经登录的状态。
2)、追踪用户行为
我们在使用HTTP网络访问,有时会看到类似下面的声明。会告诉我们网站使用Cookies不会进行用户行为追踪,侵犯用户隐私。
Cookie进行用户行为追踪的原理,就是当我们进行网络请求时,可能请求的内容,比如图片,还需要再向第三方网站进行请求。服务器发给我们资源地址时会带有“form=xxx“的信息,表示该请求的来源。这些信息被三方网站获取,就可以掌握用户访问过哪些网页。通过用户网络行为,对用户进行画像。
1.4 Cookie相关攻击
与Cookie有关的网络攻击,主要用XSS和XSRF两种。
XSS
Cross-site scripting的缩写,意思是“跨站脚本攻击“。攻击的原理是javaScrip可以在客户端本地拿到Cookies,并发送到自己的网站,进而盗用用户的身份信息。
针对这种攻击,服务器在发送“set-Cookie“时,对敏感的信息,增加”HttpOnly“修饰。它表示该Cookie只在进行HTTP请求时自动发送,不能被本地javaScrip调用。
它的报文格式:Set-Cookie: client_id=123;HttpOnly
XSRF
Cross-site request forgery的缩写,意思是“跨站请求伪造“。它是在用户不知情的情况下,访问恶意网站,该网站使用用户Cookie向目标服务器发起请求,以此来越权操作用户的账号。
比如,用户登录网银,首先进入恶意网站,恶意网站使用我的Cookie来登录网银。
针对这种攻击,在服务器端增加“Referer”校验。Referer机制,是浏览器每次跳转时会强制加上,用于标记转发的网站。如果直接访问目标网址Referer为空。
服务器端通过只处理没有跳转的(Referer为空)请求,或者来自白名单网站转发的请求,来防范XSRF攻击。
-
二、Authorization
Authorization,即“许可、授权”的意思。它被设计出来就是用于登录鉴权。实际上它比Cookie更适合用于登录状态管理。它有两种主要的Token:Basic和Bearer。Basic用于登录授权,Bearer用于进行第三方登录。
在介绍Authorization之前,先看一个知识点Base64。
2.1 Base64
Base64是一种编码格式,它是将二进制数据转换成由64个字符组成的字符串。这64个字符是a~z、A~Z、0~9、“+”和“\”,共64个字符。
转换的方式,是将原二进制串按照每六个字符进行分割,根据base64码表确定字符。(我们知道计算机字符是按照每八个字符分割)。
Base64码表如下:
看一下,下面的例子,原字符串“Man”,按照Base64重新编码成了”TWFu”。
码表中“=”的作用是当最后不够6个字符时,用来进行补位。
如下,“Ma”的Base64格式“TWE=”。“M”的base64格式是“TQ==”。
了解了Base64编码原理我们知道它是不安全的,因为编码后的数据,可以很容易反编码回去;同时也是低效的,经过Base64编码,原字符串会变得更长,传输的数据体积更大。
Base64的作用就是把普通的二进制数据,全部转为字符串的形式。同时当原数据是字符串时,经过编码可以起到防偷窥的作用。
扩展知识:Base58
Base58是Base64的变种,它在Base64码表的基础上去掉了容易混淆的O (大写的o)、0(零)、I(大写的i)、 l(小写的L),以及“+”和“\”六个字符。它被设计出来用于比特币地址的存储,防止在进行手抄时抄错。
2.2 Basic
使用Basic形式的Token用于登录授权的HTTP报文形式如:
Base64数据是“zhangsan:1234567”。
这种方式会有Base64被破解和Token在本地被窃取风险。
针对Base64破解风险,可采用HTTPS进行数据传输,它会将请求数据全部加密,Base64值同样会被加密,就不会被破解了。
Token在本地被窃取,大多数情况是不需要担心的。Token虽然被保存到本地,手机端的安全机制下,这个数据是不会被其他应用获取的。少数情况,下用户刷机并给恶意三方程序root最高权限,而可以访问任何文件,token才可能被窃取。这种情形相当于用户主动放弃了安全机制,是用户自主行为。
2.3 Bearer
是“持票人”的意思。拿着有权限人给的“票据”,就可以被赋予相应的权限。
报文形式是:Authorization: Bearer <bearer token>
这里的token就是授权发发来的“票据”。现在基本都是通过OAuth2的方式进行获取。后面结合三方登录授权的实现原理,理解Bearer的用法。
三、第三方登录实现原理
3.1 第三方登录
我们可能经常见到类似下图的登录界面,在“其他登录方式”中,可以选择用微信、QQ等知名应用进行授权登录。
比如选择微信,则跳转到微信界面,在微信界面点击“确认登录”。再次返回到该应用,则完成了登录。
这种登录方式就是“第三方登录”。
它早期是由美国人发明,像使用fecebook进行三方授权对用户来说就会很方便,当时叫做“社交网络登录”。后来这项技术传到中国,改叫“第三方登录”。
3.2 OAuth2授权流程
第三方登录是通过OAuth2实现的。下面结合抖音使用微信进行登录的例子,看一下它的整个流程。
1、在抖音登录界面点击“使用微信登录”后,将跳转到微信界面,并将“client-id”发送给微信。“clent-id”是抖音在开发时,向微信申请的。相当于取得的授权资质。
2、在微信上根据client-id显示抖音软件的信息。同样这个信息,也是抖音在早期开发时给微信的。
3、用户在微信界面点击“确认登录”,微信向微信服务器请求“授权码”。然后将“授权码”发给抖音,微信客户端关闭。
4、抖音拿到“授权码”后,发给抖音服务器。抖音服务器使用“授权码”和“client_secret”向微信服务器申请bearer token。“client_secret”和上面的“client-id”,它是在抖音服务器开发时向微信服务器申请的。并且它是严格保密的信息,服务器与服务器之间的通讯都是采用HTTPS完成。抖音服务器获取到bearer token后,就相当于拥有了”票据”。
5、抖音服务器使用token向微信服务器请求用户头像、id、昵称等。像微信自己向服务器请求一样。用这些信息帮用户申请账号,然后帮用户进行登录。如果账号已存在则直接进行登录。
6、服务器端完成登录成功后,将登录状态发回给抖音客户端,进行显示。完成整个三方登录过程。
以上就是OAuth2授权的完整流程,也是第三方登录的完整过程。“第三方登录”是一个产品名称,使用的技术是“第三方授权”。
3.3 错误用法
在实际的开发中,有一种错误的做法是登录服务器将“token”发给登录客户端,由客户端请求用户信息。
这样做会因减少交互的流程而减少用户登录时间。但是不建议这样做,因为不安全。攻击者会很容易获得token,造成token的泄漏。
3.4 Refresh Token
下面简单介绍下有关token的操作。重点讲一下Refresh Token。
有关token的请求命令有四种:
token_type : 获取token的类型,如bearer、basic;
access_token: 请求token;
refresh_token: 刷新token;
expires_time: 获取token有效时间。
在很多情况下,为避免token泄漏,token会定期被废掉。三方授权登录后,如果token过期,则会导致登录失效,需要用户重新进行登录。而为了避免因此而打扰用户,通常三方服务器会定时进行Reresh token,在用户无感的情况下,帮用户完成定期登录。这就是Refresh Token的意义。