Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【bigo】谈谈登录 #11

Open
DubeChen opened this issue Dec 1, 2020 · 0 comments
Open

【bigo】谈谈登录 #11

DubeChen opened this issue Dec 1, 2020 · 0 comments

Comments

@DubeChen
Copy link

DubeChen commented Dec 1, 2020

谈谈登录

一、Cookie与Session

HTTP是无状态协议,它不对之前发生过的请求和响应的状态进行保存。因为无法管理用户状态,对于要登录的页面,每次跳转新页面时都需要再次登录。
于是引入了Cookie来管理用户状态:
① 首先客户端发起不带Cookie信息的登录请求
② 服务端接收到请求,验证用户数据正确后,添加响应头Set-Cookie
③ 客户端收到响应报文后,检查到响应头Set-Cookie,在本地保存Cookie
④ 之后每次向该域发起请求时,自动添加请求头Cookie,发送给服务端
⑤ 服务端获取请求头Cookie,根据Cookie的值,就可以判断出用户是否登录

但是Cookie极容易被篡改和伪造,于是产生了Session,Session将用户信息保存在服务端,那么Session是如何管理用户状态的呢?
① 首先客户端发起不带Cookie信息的登录请求
② 服务端接收到请求,检查到没有携带口令,验证用户密码正确后生成Session,将用户信息保存在Session,设置响应头Set-Cookie,通常是将Session ID作为口令值
③ 客户端检查到Set-Cookie响应头,在本地保存Cookie信息
④ 之后每次发起请求时,自动在请求头Cookie中携带口令,发送给服务端
⑤ 服务端获取Cookie携带的口令值,找到对应的Session,就可以判断用户状态

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

虽然口令值由服务端生成,用户不容易伪造,But nothing is impossible;而且口令值存在客户端,就有可能被盗用。一旦口令值被伪造或盗用,攻击者就可以伪装成用户访问服务端的数据。
那么如何让Session口令值更安全呢?
① 将客户端的某些独有信息+口令值作为原值,对其进行签名
② 将口令值拼接签名返回给客户端,将Cookie设置为HttpOnly(禁止用户通过脚本来获取和更改Cookie)
③ 服务端再次收到请求,取客户端信息与口令值签名,与客户端携带的签名对比,不相等,说明请求不合法

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

三、多系统的复杂性

web系统由早期的单系统发展成多系统组成的应用群,面对如此众多的系统,用户难道要一个个登录、再一个个注销吗?
系统复杂性应该由系统内部承担,而不是用户。无论web系统内部多么复杂,对用户而言,都是一个统一的整体,也就是说,用户访问web系统的整个应用群与访问单个系统一样,只要登录/注销一次就够了。
image
因为Cookie不允许跨域,早期多系统登录采用将Cookie种在顶级域名下的方式,来实现Cookie共享。这种方式的局限在于:
① 应用群各系统的域名得统一
② 应用群各系统的web服务端使用的技术要相同,比如Session口令值以及它的签名
方式要相同,要不Session口令值不同,无法维持会话
因此,我们需要一种全新的登录方式来实现多系统应用群的登录,这就是单点登录。

四、单点登录

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

1、单点登录

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

image

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

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

2、单点注销
单点登录自然也要单点注销,在一个子系统中注销,所有子系统的会话都将被销毁。
image
 用户向系统1发起注销请求
 系统1根据用户与系统1建立的会话拿到Token,向SSO认证中心发起注销请求
 SSO认证中心校验Token有效,销毁全局会话,同时取出所有用此Token注册的系统地址
 SSO认证中心向所有注册系统发起注销请求
 各注册系统接收SSO认证中心的注销请求,销毁局部会话
 SSO认证中心引导用户至登录页面

五、登录安全防范

1、CSRF攻击
CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的登录凭证,绕过后台的用户验证,达到冒充用户对被攻击网站执行某项操作的目的。
一个典型的CSRF攻击有着如下的流程:
① 受害者登录网站a,并保留了登录凭证Cookie
② 攻击者引诱受害者访问网站b,它向网站a的服务器发送了一个跨站请求,该请求会默认携带网站a的Cookie
③ 网站a的服务器接收到请求后,对请求进行验证,确认是受害者的凭证,误以为是受害者自己发送的请求,以受害者的名义执行某个操作
④ 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让网站a执行了攻击者自己定义的操作

CSRF通常发生在第三方域名,由于浏览器同源策略的限制,攻击者不能获取到受害者的Cookie信息,只是冒用。针对这2点,我们可以制定相应的防护策略:
1)同源检测
服务器通过解析Origin 或Referer这两个请求头,确定请求的来源域,如果请求来自外域,直接阻止。
缺点:在部分情况下,攻击者可以隐藏甚至修改自己请求的Referer;会误伤一些正常请求,比如通过搜索结果跳转的页面请求。

2)Samesite Cookie
为了从源头上解决CSRF攻击,Google起草了一份草案来改进HTTP协议,即为响应头Set-Cookie新增Samesite属性:
Strict:任何情况下都不可能作为第三方Cookie,其它网站发起的任意请求都不会携带上该Cookie,包括搜索页面。
Lax:用户在不同网站之间通过链接跳转不受影响;但假如这个请求是从其它网站发起的请求,或者页面跳转是通过表单POST提交触发的,则Cookie也不会携带发送。
缺点:目前还并不成熟,其应用场景有待观望。

3)双重Cookie
① 在用户访问网站页面时,向请求域名注入两个Cookie,一个是原本要注入的Cookie,一个比如随机字符串
② 前端向后端发起请求时,取出随机字符串,添加到URL参数或请求头中
③ 后端验证携带的随机数与Cookie中的随机数是否一致,不一致则拒绝请求
缺点:难以做到子域名隔离,认证Cookie必须被种在顶级域名下,每个子域才可以访问;如果某个子域存在XSS漏洞,攻击者将这个认证Cookie修改为自己配置的Cookie;攻击者直接使用自己配置的Cookie发起CSRF攻击。

4)CSRF Token
CSRF攻击者无法直接窃取到用户的Cookie,仅仅是冒用;而CSRF攻击之所以能够成功,是因为服务器误把攻击者发送的请求当成了用户的请求。
① 服务器生成登录Cookie时,同时生成Token和Token签名的2个Cookie
② 前端向后端发起请求时,将Token添加到URL参数或请求头中
③ 后端收到请求,首先验证参数与Token相不相同,不相同则中止请求;然后校验签名,不相同则中止请求。因为攻击者不知道密钥,使用Token签名可以防止Cookie被篡改和伪造。
缺点:每个请求都需要携带Token,且需要服务端对每个请求进行校验。所以一般只对包含敏感数据的请求做此处理。

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

常见防范手段:
 短信发送间隔设置
 发送量限制
 图文验证码
 触发流程限制

六、全球部署问题

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

@DubeChen DubeChen changed the title 谈谈登录 【bigo】谈谈登录 Dec 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant