登录和授权
登录和授权使用的方式
Cookie
Cookie是个机制,浏览器只做存。修改是服务器通过set cookie发给浏览器。
由来:购物车
工作机制:
客户端发送购物车信息给服务器,服务器接收到后Set-Cookie(其中cart只是个名字是服务端定的)返回给客户端(服务器不存储)
客户端接收到Set-Cookie存储Cookie。
客户端再次发送新消息时把Cookie信息带过去,服务器接收到后Set-Cookie全部返回给客户端,客户端接收到Set-Cookie信息存储Cookie信息。作用:
- 会话管理:登录状态、购物车等
- 个性化:用户偏好、主题
- Tracking:分析用户行为
- 会话管理:登录状态、购物车等
XSS(Cross-site scripting)(了解即可):HttpOnly
跨站脚本攻击。即使⽤ JavaScript 拿到浏览器的Cookie 之后,发送到⾃⼰的网站,以这种⽅式来盗取⽤户 Cookie。应对⽅式:Server 在发送Cookie 时,敏感的 Cookie 加上 HttpOnly。
- 应对⽅式:HttpOnly——这个 Cookie 只能⽤于 HTTP 请求,不能被 JavaScript 调⽤。它可以防⽌本地代码滥⽤ Cookie。
如:
Set-Cookie:sessionId=123;HttpOnly
XSRF(Cross-site request forgery)(了解即可):Referer
跨站请求伪造。即在⽤户不知情的情况下访问已经保存了 Cookie 的⽹站,以此来越权操作⽤户账户(例如盗取⽤户资⾦)。应对⽅式主要是从服务器安全⻆度考虑,就不多说了。
- 应对⽅式:Referer 校验。(历史原因,正确单词是referrer)
referer记录的是从哪个网站过来的
Authorization
两种主流方式:Basic和Bearer
Basic:
- 格式:
Authorization:Basic <username:password(Base64ed)>
通过计算得来的 - 例子:github的token给客户端登录
Bearer:(持票人)
- 格式:
Authorization:Bearer <bearer token>
让授权方给予 - bearer token
OAuth2:(第三方验证)
OAuth2流程
1 | get /user http/1.1 |
例子:掘金网站用第三方github登录方式(github给掘金授权);第三方登录的第三方是github,第三方授权的第三方是掘金;流程:github授权(访问一些关键信息的权限)给掘金,掘金有了权限后再去获取github的头像、昵称等信息(这一过程github并不知道它登录了哪里),掘金拿到信息登录的过程它是第一方。
第三方登录是产品角度的叫法。在技术角度只是授权(Authorize)访问一些头像昵称等信息(那个“第三方”根本不知道它登录了啥)
这个client_id是开发这个3rd-party.com的时候向github平台注册的,github平台给这个平台分配的client_id
3rd-party.com使用“github第三方登录”方式
github返回Authorization Code给登录的网站,这个网站就能根据这个code去获取github上的头像等信息
其中的client_secret不能丢,否则坏人就能拿它去做坏事
完整流程:
步骤:
- 开发者先在 github.com 这个第三方平台上进行注册,会得到 client_id 和 client_secret;
- 在浏览器上访问 github.com 获取授权的时候会把 client_id 带过去;
- github.com 收到 client_id 会返回一个授权码 Authorization code;
- 浏览器获取到授权码后提交给后台(为了安全,浏览器不可信任);
- 后台接收到 Authorization code 后,再把它和 client_secret 一起发送到 github.com 来获取 access_token;这样整个 OAuth2 流程就完成了。
后续向 github.com 请求个人头像等信息只要让服务器带上 access_token 即可(”bearer+值”的形式)
微信登录
是个完整的OAuth2流程
为了安全考虑:
客户端获取到微信授权码Authorization Code后,应该给服务端,服务端去跟微信的服务端通信,获取微信的access token等信息,再提供给客户端。客户端不应该拿token和Secret
自家App中使用Bearer token
App获取到token后,下次请求直接带上给服务端
refresh token
为了安全,token失效了不让客户重新授权,直接告诉第三方github让原来的token失效掉
1 | post /refresh_token http/1.1 |
TCP/IP协议族
由于网络的不稳定,需要网络分层模型
- Application Layer应用层:HTTP、FTP、DNS
- Transport Layer传输层:TCP、UDP
TCP:会把数据分包进行传,失败会重传(数据严谨性)
UDP:不是所有场景需要重传,比如游戏 - Internet Layer网络层:IP
IP层(寻址作用)接收到就往目的传,不关心传成功与否 - Link Layer数据链路层:以太网、Wi-Fi
实际传输数据
TCP 连接(是有状态的)
通信双⽅建⽴确认「可以通信」,不会将对⽅的消息丢弃,即为「建⽴连接」
TCP 连接的建⽴与关闭
三次握手(连三下)
- 请求方发送消息给接收方:我要给你发消息了
- 接收方发送消息给请求方:好的,我知道了,我也要给你发消息了
- 请求方发送消息给接收方:好的,我知道了
四次挥手(连四下)
- 请求方发送消息给接收方:我不给你发消息了
- 接收方发送消息给请求方:好的,我知道了(可能还有消息没发完,所以不告诉请求方进行关闭)
- 接收方发送消息给请求方:(他把消息发完了)我不给你发消息了
- 请求方发送消息给接收方:好的,我知道了(此时TCP连接关闭)
长连接
为什么要长连接?
因为移动网络并不在 Internet 中,而是在运营商的内网,并不具有真正的公网 IP,因此当某个TCP 在一段时间不通信后网关会考虑网络性能而关闭这条 TCP 连接和公网的连接通道,那么这个 TCP端口不再收到外部通信消息,即 TCP连接被动关闭。
长连接的实现方式
心跳。在一定时间间隔内使用 TCP 发送超短无意义消息来让网关不能把这个连接归为“空闲连接”,从而防止这个连接被关闭。
HTTPS
定义
HTTP over SSL的简称,即工作在SSL(或TLS)上的HTTP。说白了就是加密通信的HTTP。
HTTP是种协议,HTTPS不是个单独的协议。是HTTP建立在SSL上的
SSL:Secure Socket Layer(以前的) -> TLS Transport Layer Secure(现在的)
HTTPS是种概念上的层,是在HTTP传输数据前进行加密再传的东西(更靠近HTTP这一层)
工作原理
本质:在客户端和服务器之间协商出一个对称密钥(用非对称加密商讨),每次发送信息之前将内容加密,收到之后解密,达到内容的加密传输。
不用非对称加密的原因
从数学方面理解,它要经过复杂的计算,效率太慢。
HTTPS 连接建⽴的过程
1 | 1. 客户端请求建立TLS连接 |
其中1~4的步骤都是TCP通信
附带随机数(后续用来计算密钥)、TLS版本、Cipher Suite(加密套件(打包一起发送的):可支持什么对称加密算法、非对称加密算法、Hash算法)
Server Hello(服务器返回“好的”)
服务器把它确定的TLS版本、Cipher [ˈsaɪfər] Suite,再附带服务端的随机数、客户端随机数返回服务器证书信任建⽴(服务器附带证书)
(用来给客户端验证是否是它要访问的服务器)
包含:
服务器地址、服务器名称等
证书公钥(是核心。是非对称加密的公钥)
证书签名(证明信息是真实的,不是别人模拟的)
证书机构的公钥及其他信息(证明证书签名是这个证书机构颁发的这条信息是真实的)
证书机构的签发方的信息(证明证书机构的信息是这个签发方签发的的这条信息是真实的)其中证书签发方的真实性是可靠的(需要无条件信任),每个系统内都有“系统根证书”列表
根证书列表是操作系统研发方验证后放在系统中的(只要操作系统、浏览器不被干掉就是安全的)Pre-master Secret
唯一一次非对称加密传过去的随机数
服务端随机数、客户端随机数、pre-master Secret
,这三个随机数通过算法计算出Master secret
,用Master secret计算对称加密的密钥Master Secret
(由客户端加密密钥、服务端加密密钥、客户端MAC Secret
、服务端MAC Secret
生成)(客户端发送消息用客户端加密密钥加密,服务端发送消息用服务端加密密钥加密)(MAC Secret
是用来验证身份的)PS:
HMAC:Hash-based Message Authenticate Code
,改良版的hash(HMAC(a)=MD5(fun(a))=c
即中间经过一些变换,使得MD5加密后得到的hash值不容易被破解,而且这个转换只有通信两方知道,要用MAC Secret
来参与转换,最终保证这个消息的真实性)客户端通知:我要使⽤加密通信了
客户端发送:Finished
其中的内容包含前面那些密钥、Finished消息,用客户端MAC Secret进行hash服务器通知:我要使⽤加密通信了
服务器发送:Finished
服务端发送的消息包含了前面的1~6的内容和它要发送的Finished消息,再用服务端MAC Secret进行hash
最后:TCP只知道有应用层消息(如:“应⽤层消息:#@R#RTERT#$TWERT”)根本不知道是什么协议,客户端和服务端发送出来的都是这种的
在 Android 中使⽤ HTTPS
正常情况
直接使⽤
什么时候会不行?
- 用的自签名证书(例如只用于内网的https)
- 证书信息不全,缺乏证书机构信息
- 什么操作系统比较旧,没有安装最新加入的根证书