type
status
date
slug
summary
tags
category
password
icon
登录和授权的区别
- 登录:身份认证,即确认「你是你」的过程。
- 授权:由身份或持有的令牌确认享有某些权限(例如获取⽤户信息)。⽽登录过程实质上的⽬的也 是为了确认权限。
因此,在实际的应⽤中,多数场景下的「登录」和「授权」界限是模糊的。
HTTP 中确认授权(或登录)的两种⽅式
- 通过 Cookie
- 通过 Authorization
Cookie
Cookie 的起源
网景公司想要做一个 Web 购物车的功能,不想把购物车的数据存在服务器。目的是为了让服务端可以把数据存在客户端。
Cookie 的工作机制
在客户端帮助服务端存储数据的机制。
- 服务器需要客户端保存的内容,放在 Set-Cookie headers ⾥返回,客户端会⾃动保存。
- 客户端保存的 Cookies,会在之后的所有请求⾥都携带进 Cookie header ⾥发回给服务器。
- 客户端保存的 Cookie 在超时后会被删除、没有设置超时时间的 Cookie (称作 Session Cookie)在浏览器关闭后就会⾃动删除;另外,服务器也可以主动删除还未过期的客户端 Cookies。
Cookie 报文中的格式
统一个主机下 Cookie 的内容可以保存多个,以键值对保存
最后面的 HttpOnly 是可选项,用于防治跨站脚本攻击,这个标记表示该 Cookie 本地javascript 无法获取。
例如,用户在 shop.com 网站上购物






Cookie 的作用
- 会话管理:登录状态,购物车
例如:获取用户的个人信息,没有登录时不能获取的,那么服务端是怎么判断用户的登录状态的呢?目前很多的做法是使用 Cookie 保存一个 SessionId,




- 个性化:用户偏好,主题
例如:用户喜欢蓝牙的主题风格,怎么在用户下次打开网站时,直接显示蓝色的网站风格 是不是可以直接把主题编号保存到客户端的 Cookie,或者与用户 ID 进行绑定,每次用户打开网站时就能知道,这个用户之前偏好蓝色的主题,并返回蓝色风格的网站页面给到用户。
- Tracking:分析用户行为
例如下图所示的方式 1.用户在 shop.com 中访问了 3rd-party.com 的图片,3rd-party.com 发现用户是通过 shop.com 跳转过来的,就给这个用户生成一个 client_id,假设时 123。然后记录下这个用户访问过 shop.com 这个网站,并返回了一个 client_id 的 Cookie 给到用户的浏览器,浏览器会自动保存, 2.某一时间,用户访问 taobao.com 网站,其中也访问 3rd-party.com 的图片,那么这次图片访问,浏览器会自动把之前保存的 client_id=123 的 Cookie 发送到3rd-party.com,并且 3rd-party.com 也知道了你是从 taobao.com 访问的,就又记录下用户 123 又访问了淘宝。 如此反复记录,能够得到用户 123 的画像。就能够针对该用户提供定向广告。往往像3rd-party.com 这种不是一个网站,而是一群商业联盟,他们都互相传递并记录用户行为,以得到更精准的用户画像,谋求更大的利益。

XSS(Cross-site scripting):HttpOnly
Cross-site scripting:跨站脚本攻击
由于 Cookie 是存在浏览器本地,javascript 能过获取到 Cookie,那么坏人就可以通过javascript 获取到 Cookie 去干坏事。
其中一种解决上述问题的方式是在报文的 set-cookie 的 key-value;的最后可以加上 HttpOnly,用于防治跨站脚本攻击,这个标记表示该 Cookie 本地 javascript 无法获取。
XSRF(Cross-site request forgery):Referer
Cross-site request forgery:跨站请求伪造
即在⽤户不知情的情况下访问已经保存了 Cookie 的⽹站,以此来越权操作⽤户账户(例如盗取⽤户资⾦)。应对⽅式主要是从服务器安全⻆度考虑,就不多说了。
由于页面跳转时浏览器会强制在跳转后的请求中加上一个 Referer 的 Header,并将跳转前的链接作为值,发送给新页面,新页面的后端如果需要安全考虑,就可以通过 Referer 这个Header 判断页面的安全性,并给出对应的响应。
应对⽅式:Referer 校验。
使用 Cookie 去登录,是大家自己摸索出来的方式,目前被广泛使用。
但是移动端目前使用的不太多。并且 Cookie 的初衷并不是用于登录,Http 设计中,Authorization 这个 Header 是专门用于登录的,并且目前也开始被使用,以后也会成为主流
Authorization
Http 默认设计的登录授权的方式就是 Authorization,Cookie 的方式是开发摸索出来的
两种主流方式:Basic 和 Bearer
Basic
格式:
例如:有一个获取用户信息的请求 假设用户名是 man,密码是 123 ,man:123 的 base64是 bWFuOjEyMw==
安全风险:
如果报文被截获,base64 是可以解码获取到原始信息的。但是在 Https 中,整个报文都是密文,被截获,报文都是加密的。
另一种,在 Android 上,账号密码的明文往往保存在包内存储的,用于免登录,由于 Android 的安全机制,包内数据无法被外部获取,但是如果手机被 root 了,安装了木马程序,那么账号密码是可以被获取的,一但被获取,就只能改密码了。
这两种属于极端情况,
Bearer
Bearer(持票人)
格式:
bearer token 的获取方式:通过 OAuth2 的授权流程
OAuth2 授权流程:
- 第三⽅⽹站向授权⽅⽹站申请第三⽅授权合作,拿到 client id 和 client secret
- ⽤户在使⽤第三⽅⽹站时,点击「通过 XX (如 GitHub) 授权」按钮,第三⽅⽹站将⻚⾯跳转到授权⽅⽹站,并传⼊ client id 作为⾃⼰的身份标识
- 授权⽅⽹站根据 client id ,将第三⽅⽹站的信息和第三⽅⽹站需要的⽤户权限展示给⽤户,并询问⽤户是否同意授权
- ⽤户点击「同意授权」按钮后,授权⽅⽹站将⻚⾯跳转回第三⽅⽹站,并传⼊Authorization code 作为⽤户认可的凭证
- 第三⽅⽹站将 Authorization code 发送回⾃⼰的服务器
- 服务器将 Authorization code 和⾃⼰的 client secret ⼀并发送给授权⽅的服务器,授权⽅服务器在验证通过后,返回 access token。OAuth 流程结束。
- 在上⾯的过程结束之后,第三⽅⽹站的服务器(或者有时客户端也会)就可以使⽤ access token 作为⽤户授权的令牌,向授权⽅⽹站发送请求来获取⽤户信息或操作⽤户账户。但这已经在 OAuth 流程之外。
例如掘金平台使用用 github 进行三方登录 授权过程如下: 拿到 access token 后,后端就拿到了 github 的授权,可以通过 access token 去访问github的获取用户头像,昵称等接口,然后通过这些用户信息在自己的服务器上注册并帮助用户登录。 一种不安全的做法是,把 access token 交给客户端自己去获取,这种方式就丧失了OAuth2 的安全性。 另一种不安全的是,客户端拿到 authorization code 后,直接去获取 access token,而不是交给后端获取。
为什么 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 做关联
- ⽤户创建完成后,服务器向客户端的请求发送响应,传送回刚创建好的⽤户信息
- 客户端收到服务器响应,⽤户登录成功
在自家软件中使用 Bearer token
有的 App 会在 Api 的设计中,将登录和授权设计成类似 OAuth2 的过程,但简化掉 Authorization code 概念。即:登录接⼝请求成功时,会返回 access token,然后客户端在之后的请求中,就可以使⽤这个 access token 来当做 bearer token 进⾏⽤户操作了。
Refresh token
⽤法:access token 有失效时间,在它失效后,调⽤ refresh token 接⼝,传⼊ refresh_token 来获取新的 access token。
⽬的:安全。当 access token 失窃,由于它有失效时间,因此坏⼈只有较短的时间来「做坏事」;同时,由于(在标准的 OAuth2 流程中)refresh token 永远只存在与第三⽅服务的服务器中,因此 refresh token ⼏乎没有失窃的⻛险。
- 作者:shuouyang
- 链接:https://notion-tree.vercel.app/article/54b4e86b-1913-4851-b4b3-8bb1d70fbad3
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。