面试官:这位同学,请你谈谈登录

file

本文首发于:https://github.com/bigo-frontend/blog/ 欢迎关注、转载。

谈谈登录

面试官简单一句提问,其实背后是希望我们能够从用户身份验证、安全防范、前后端交互流程等方面回答,本文系统性对登录涉及的知识点进行了梳理,希望大家有所收获。

一、Cookie与Session

HTTP是无状态协议,它不对之前发生过的请求和响应的状态进行保存。因为无法管理用户状态,对于要登录的页面,每次跳转新页面时都需要再次登录。
于是引入了Cookie来管理用户状态:

  1. 首先客户端发起不带Cookie信息的登录请求
  2. 服务端接收到请求,验证用户数据正确后,添加响应头Set-Cookie
  3. 客户端收到响应报文后,检查到响应头Set-Cookie,在本地保存Cookie
  4. 之后每次向该域发起请求时,自动添加请求头Cookie,发送给服务端
  5. 服务端获取请求头Cookie,根据Cookie的值,就可以判断出用户是否登录

但是Cookie极容易被篡改和伪造,于是产生了Session,Session将用户信息保存在服务端,那么Session是如何管理用户状态的呢?

  1. 首先客户端发起不带Cookie信息的登录请求
  2. 服务端接收到请求,检查到没有携带口令,验证用户密码正确后生成Session,将用户信息保存在Session,设置响应头Set-Cookie,通常是将Session ID作为口令值
  3. 客户端检查到Set-Cookie响应头,在本地保存Cookie信息
  4. 之后每次发起请求时,自动在请求头Cookie中携带口令,发送给服务端
  5. 服务端获取Cookie携带的口令值,找到对应的Session,就可以判断用户状态

二、如何让Session口令值更安全

虽然口令值由服务端生成,用户不容易伪造,But nothing is impossible;而且口令值存在客户端,就有可能被盗用。一旦口令值被伪造或盗用,攻击者就可以伪装成用户访问服务端的数据。
那么如何让Session口令值更安全呢?

  1. 将客户端的某些独有信息+口令值作为原值,对其进行签名
  2. 将口令值拼接签名返回给客户端,将Cookie设置为HttpOnly(禁止用户通过脚本来获取和更改Cookie)
  3. 服务端再次收到请求,取客户端信息与口令值签名,与客户端携带的签名对比,不相等,说明请求不合法

这样的话:

  1. 即使攻击者知道了口令值,由于不知道密钥,无法伪造签名
  2. 即使攻击者通过某种方式得到了真实的口令值和签名,但是由于攻击者的客户端信息不一样,发送到服务端后,会得到不一样的签名,签名校验不能通过

三、多系统的复杂性

web系统由早期的单系统发展成多系统组成的应用群,面对如此众多的系统,用户难道要一个个登录、再一个个注销吗?
系统复杂性应该由系统内部承担,而不是用户。无论web系统内部多么复杂,对用户而言,都是一个统一的整体,也就是说,用户访问web系统的整个应用群与访问单个系统一样,只要登录/注销一次就够了。
image
因为Cookie不允许跨域,早期多系统登录采用将Cookie种在顶级域名下的方式,来实现Cookie共享。这种方式的局限在于:

  1. 应用群各系统的域名得统一
  2. 应用群各系统的web服务端使用的技术要相同,比如Session口令值以及它的签名
    方式要相同,要不Session口令值不同,无法维持会话

因此,我们需要一种全新的登录方式来实现多系统应用群的登录,这就是单点登录。

四、单点登录

单点登录全称Single Sign On(简称SSO),是指在多系统应用群中登录一个系统,便可在其它所有系统中得到授权而无需再次登录。包括单点登录与单点注销两部分:

单点登录

相比于单系统登录,SSO需要一个独立的认证中心,只有认证中心能接受用户的用户名密码等安全信息,其它系统不提供登录入口,只接受认证中心的间接授权。
通常SSO认证中心验证用户数据没问题后,会创建授权Token,分发给各个子系统。子系统拿到Token,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。这个过程,也就是单点登录的原理。

image

例如:

  1. 用户访问系统1,系统1发现用户未登录,跳转至SSO认证中心,并将自己的地址作为参数
  2. SSO认证中心发现用户未登录,将用户引导至登录页面
  3. 用户输入用户名密码提交登录申请
  4. SSO认证中心校验用户信息,创建用户与SSO认证中心之间的会话,称为全局会话,同时创建授权Token
  5. SSO认证中心带着Token跳转回最初的请求地址(系统1)
  6. 系统1拿到Token,去SSO认证中心校验Token是否有效
  7. SSO认证中心校验Token,返回有效,注册系统1
  8. 系统1使用该Token创建与用户的会话,称为局部会话,返回受保护资源
  9. 用户访问系统2的受保护资源
  10. 系统2发现用户未登录,跳转至SSO认证中心,并将自己的地址作为参数
  11. SSO认证中心发现用户已登录,跳转回系统2的地址,并附上令牌
  12. 系统2拿到令牌,去SSO认证中心校验令牌是否有效
  13. SSO认证中心校验令牌,返回有效,注册系统2
  14. 系统2使用该令牌创建与用户的局部会话,返回受保护资源

用户登录成功之后,会与SSO认证中心及各个子系统建立会话,用户与SSO认证中心建立的会话称为全局会话,用户与各个子系统建立的会话称为局部会话,局部会话建立之后,用户访问子系统受保护资源将不再通过SSO认证中心,全局会话与局部会话有如下约束关系:

  1. 局部会话存在,全局会话一定存在
  2. 全局会话存在,局部会话不一定存在
  3. 全局会话销毁,局部会话必须销毁

单点注销

单点登录自然也要单点注销,在一个子系统中注销,所有子系统的会话都将被销毁。
image

  1. 用户向系统1发起注销请求
  2. 系统1根据用户与系统1建立的会话拿到Token,向SSO认证中心发起注销请求
  3. SSO认证中心校验Token有效,销毁全局会话,同时取出所有用此Token注册的系统地址
  4. SSO认证中心向所有注册系统发起注销请求
  5. 各注册系统接收SSO认证中心的注销请求,销毁局部会话
  6. SSO认证中心引导用户至登录页面

五、登录安全防范

CSRF攻击

CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的登录凭证,绕过后台的用户验证,达到冒充用户对被攻击网站执行某项操作的目的。

一个典型的CSRF攻击有着如下的流程:

  1. 受害者登录网站a,并保留了登录凭证Cookie
  2. 攻击者引诱受害者访问网站b,它向网站a的服务器发送了一个跨站请求,该请求会默认携带网站a的Cookie
  3. 网站a的服务器接收到请求后,对请求进行验证,确认是受害者的凭证,误以为是受害者自己发送的请求,以受害者的名义执行某个操作
  4. 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让网站a执行了攻击者自己定义的操作

CSRF通常发生在第三方域名,由于浏览器同源策略的限制,攻击者不能获取到受害者的Cookie信息,只是冒用。针对这2点,我们可以制定相应的防护策略:

1)同源检测

服务器通过解析Origin 或Referer这两个请求头,确定请求的来源域,如果请求来自外域,直接阻止。
缺点:在部分情况下,攻击者可以隐藏甚至修改自己请求的Referer;会误伤一些正常请求,比如通过搜索结果跳转的页面请求。

2)Samesite Cookie

为了从源头上解决CSRF攻击,Google起草了一份草案来改进HTTP协议,即为响应头Set-Cookie新增Samesite属性:

  1. Strict:任何情况下都不可能作为第三方Cookie,其它网站发起的任意请求都不会携带上该Cookie,包括搜索页面。
  2. Lax:用户在不同网站之间通过链接跳转不受影响;但假如这个请求是从其它网站发起的请求,或者页面跳转是通过表单POST提交触发的,则Cookie也不会携带发送。
    缺点:目前还并不成熟,其应用场景有待观望。
3)双重Cookie
  1. 在用户访问网站页面时,向请求域名注入两个Cookie,一个是原本要注入的Cookie,一个比如随机字符串
  2. 前端向后端发起请求时,取出随机字符串,添加到URL参数或请求头中
  3. 后端验证携带的随机数与Cookie中的随机数是否一致,不一致则拒绝请求
    缺点:难以做到子域名隔离,认证Cookie必须被种在顶级域名下,每个子域才可以访问;如果某个子域存在XSS漏洞,攻击者将这个认证Cookie修改为自己配置的Cookie;攻击者直接使用自己配置的Cookie发起CSRF攻击。
4)CSRF Token

CSRF攻击者无法直接窃取到用户的Cookie,仅仅是冒用;而CSRF攻击之所以能够成功,是因为服务器误把攻击者发送的请求当成了用户的请求。

  1. 服务器生成登录Cookie时,同时生成Token和Token签名的2个Cookie
  2. 前端向后端发起请求时,将Token添加到URL参数或请求头中
  3. 后端收到请求,首先验证参数与Token相不相同,不相同则中止请求;然后校验签名,不相同则中止请求。因为攻击者不知道密钥,使用Token签名可以防止Cookie被篡改和伪造。
    缺点:每个请求都需要携带Token,且需要服务端对每个请求进行校验。所以一般只对包含敏感数据的请求做此处理。

短信防刷

短信轰炸是指攻击者利用从各个网站上找到的发送动态短信的URL和前端输入的被攻击者的手机号码,发送HTTP请求,每次请求给用户发送一个动态短信。
危害:增加公司的运营成本,因为短信是需要计费的;被攻击者大量被动接收非自身请求的短信,造成无法正常使用移动运营商业务;给公司形象造成极大影响,因为一般短信会带公司签名。

常见防范手段:

  1. 短信发送间隔设置
  2. 发送量限制
  3. 图文验证码
  4. 触发流程限制

六、全球部署问题

Session存在内存里随着用户的增多会导致内存溢出,且不能跨进程、跨机器共享,且重启进程后会导致Session丢失,所以Session通常会存在第三方缓存,比如Redis里。
Redis全球部署带来的问题在于,已登录的用户再次请求时,如果请求定位到不同集群的Redis,会导致登录状态失效。
解决方案:

  1. 不同集群Redis数据同步
  2. 保证相同集群的Web服务请求同一集群的Redis

欢迎大家留言讨论,祝工作顺利、生活愉快!

我是bigo前端,下期见。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值