计算机网络-登录和授权
登录和授权的区别
- 登录:身份认证,即确认「你是你」的过程。
- 授权:由身份或持有的令牌确认享有某些权限(例如获取用户信息)。而登录过程实质上的⽬的也是为了确认权限。
登录和授权的两种方式
Cookie Header
Authorization Header
Cookie
可以把任何服务器希望存在用户本地的数据都存在用户本地。
可以认为是浏览器的缓存。
是一个
Header
,也是一种信息存储机制。同一个服务器可以用多个
Cookie
,只要每个Cookie
的名字不一样就行了。
工作机制
服务器需要客户端保存的内容,放在
Set-Cookie
headers 里返回,客户端会自动保存。客户端保存的 Cookies,会在之后的所有请求里都 自动 携带进
Cookie
header 里发回给服务器。客户端保存
Cookie
是按照 服务器域名 来分类的,例如 shop.com 发回的Cookie
保存下来以后,在之后向 games.com 的请求中并不会携带。客户端保存的
Cookie
在超时后会被删除、没有设置超时时间的Cookie
(称作Session Cookie
)在浏览器关闭后就会自动删除;另外,服务器也可以主动删除还未过期的客户端 Cookies。
缺点
出现 Cookie
的时候还没有 JavaScript
语言,所以不能对 Cookie
进行浏览器本地计算,必须要将 Cookie
传到服务器处理。
作用
会话管理:登录状态、购物车等
移动开发通常也只将 Cookie 用于登录状态管理,且现在也越来越少的进行使用了。
使用
Cookie
管理登录状态客户端向服务器发送用户名和密码后,当服务器验证用户登录成功后,会通过
Set-Cookie
向客户端传输一个SessionId
的字段。SessionId
可以是记录了用户此次登录的会话编号。此后客户端每次发送请求的时候通过携带该
Cookie
便可将HTTP
从无状态变为有状态。当服务器从数据库中发现存在一样的
SessionId
后,便可确认用户的身份信息了。个性化:用户篇好、主题等
如果由服务器网页有多个主题以及其他个性化内容的话,可以通过存储
client_id
等相似字段记录用户的选择,从而记录并显示用户的偏好。Tracking:分析用户行为,追踪用户行为。
通过记录用户访问的网站信息或者其他信息,可以更加方便得向用户推广广告。
XSS(Cross-site scripting)
跨站脚本攻击。通过 JavaScript
获取客户端浏览器中的 Cookie
并利用其中的信息,如网站登录信息等。
可以通过 HttpOnly
进行防护,作用是让 Cookie
只能用于发送请求时自动携带,而无法通过 JavaScript
主动获取。添加方法形如 Set-Cookie:session_id=123;HttpOnly
即可。
XSRF(Cross-site request forgery)
跨站请求伪造。在用户不知情的情况下访问了一个用户保存了 Cookie
的网站,以此来进行一些越权操作。
例如,私自访问用户保存了 Cookie
的银行网站并通过添加 url
参数来进行转账操作等等。
可以通过 Referer
校验解决,通过在发送请求的时候 自动且强制 在 Header 中添加 Referer
参数,参数保存了从哪一个网址跳转进入了该网址。服务器只需要校验 Referer
参数是否在白名单中即可保证访问安全。
Authorization
目前较
Cookie
更加流行。
两种用法
Basic token
格式:Authorization: Basic <username:password(Base64ed)>
。其中,<username:password(Base64ed)>
部分是将 username:password
格式的字符串进行 Base64
处理后重新替换到 Basic
后面。
服务器对 token 进行校验,如果校验通过,那么授权验证通过,客户端就可以获取到用户信息。如果数据不对,那么就获取不到用户信息,服务器对报 401 错误,即权限不足。
Bearer token
Bearer : n. 拿着的人,持票人
格式:Authorization: Bearer <bearer token>
。<bearer token>
是授权方发给我们的 access token
。
access token
获取方法
OAuth2
流程
第三方网站向授权方网站申请第三方授权合作,拿到
client_id
和client_secret
client_id
:申请授权的 app 的 id。client_secret
:需要严格保密,保存在第三方网站服务器中,作为密码的作用,证明是第三方网站自己申请的授权。用户在使用第三方网站时,点击「通过 XX (如
GitHub
) 授权」按钮,第三方网站将页面跳转到授权方网站,并传入client_id
作为自己的身份标识。授权方网站根据
client_id
,将第三方网站的信息和第三方网站需要的用户权限展示给用户,并询问用户是否同意授权用户点击「同意授权」按钮后,授权方网站将页面跳转回第三方网站,并传入
Authorization code
作为用户认可的凭证。第三方网站将
Authorization code
发送回自己的服务器。服务器将
Authorization code
和自己的client_secret
⼀并发送给授权方的服务器,授权方服务器在验证通过后,返回access token
。OAuth 流程结束。在上面的过程结束之后,第三方网站的服务器(或者有时客户端也会)就可以使用
access token
作为用户授权的令牌,通过Authorization: Bearer <access token>
向授权方网站发送请求来获取用户信息或操作用户账户。但这已经在 OAuth 流程之外。
为什么
OAuth
要引入Authorization code
,并需要申请授权的第三方将Authorization code
发送回自己的服务器,再从服务器来获取access token
, 而不是直接返回access token
?这样复杂的流程意义何在?为了安全。
OAuth
不强制授权流程必须使用HTTPS
,因此需要保证当通信路径中存在窃听者时,依然具有足够高的安全性。
微信登录流程
第三方 App 通过微信登录的流程,也是一个 OAuth2
流程:
- 第三方 App 向腾讯申请第三方授权合作,拿到
client_id
和client_secret
- 用户在使用第三方 App 时,点击「通过微信登录」,第三方 App 将使用微信 SDK 跳转到微信,并传入自己的
client_id
作为自己的身份标识 - 微信通过和服务器交互,拿到第三方 App 的信息,并显示在界面中,然后询问用户是否同意授权该 App 使用微信来登录。
- 用户点击「使用微信登录」后,微信和服务器交互将授权信息提交,然后跳转回第三方 App,并传入
Authorization code
作为用户认可的凭证。 - 第三方 App 调用自己服务器的「微信登录」API,并传入
Authorization code
,然后等待服务器的响应。 - 服务器在收到登录请求后,拿收到的
Authorization code
去向微信的第三方授权接口发送请求,将Authorization code
和自己的client_secret
一起作为参数发送,微信在验证通过后,返回access token
。 - 服务器在收到
access token
后,立即拿着access token
去向微信的用户信息接口发送请求,微信验证通过后,返回用户信息。 - 服务器在收到用户信息后,在自己的数据库中为用户创建一个账户,并使用从微信服务器拿来的用户信息填入自己的数据库,以及将用户的 ID 和用户的微信 ID 做关联。
- 用户创建完成后,服务器向客户端的请求发送响应,传送回刚创建好的用户信息。
- 客户端收到服务器响应,用户登录成功。
在自家 App 中使用 Bearer token
登录
有的 App 会在 API 的设计中,将登录和授权设计成类似 OAuth2 的过程,但简化掉 Authorization code
概念。
即:登录接口请求成功时,会直接返回 access token
,然后客户端在之后的请求中,就可以使用这个 access token
来当做 bearer token
进行用户操作了。
Refresh token
1
2
3
4
5
6
{
"token_type": "Bearer",
"access_token": "xxxxx",
"refresh_token": "xxxxx",
"expires_time": "xxxxx"
}用法:
access token
有失效时间,在它失效后,调⽤refresh_token
接口,传入refresh_token
来获取新的access token
。目的:
- 安全。当
access token
失窃,由于它有失效时间,因此坏人只有较短的时间来「做坏事」。- 同时,由于(在标准的
OAuth2
流程中)refresh token
永远只存在与第三方服务的服务器中,因此refresh token
几乎没有失窃的风险。