Android 网络全栈攻略(二)—— 登录与授权

在上一篇Android 网络全栈攻略(一)—— HTTP 协议基础中我们讲解 HTTP Header 时保留了 Cookie / Set-Cookie、Authorization 没有讲,目的是放在本篇中与登录和授权相关的知识一起讲解。

本篇主要讲述 Cookie 的工作机制、第三方登录与第三方授权的概念及流程:

  • 介绍 Cookie 在网络通信中的作用,包括存储会话信息、管理用户偏好及行为追踪,并提及 Cookie 的安全性和逐渐被Authorization Header 取代的趋势
  • 深入讲解第三方登录与授权的区别,通过实例说明第三方登录的流程,包括 token 的使用、服务器与客户端的交互等
  • 介绍了 access token 和 refresh token 的作用,以及 authorization 的两种主流工作方式

1、登录与授权简介

登录(Authentication)与授权(Authorization)是信息安全中两个核心但易混淆的概念。它们共同构成资源保护的基础,但作用阶段和目标截然不同:

概念目标关键问题示例
登录(认证)验证用户身份是否合法“你是谁?”输入用户名密码、指纹识别
授权控制用户对资源的访问权限“你能做什么?”管理员可删帖,普通用户只能浏览

登录的本质是进行身份认证,是确认“你是你”的过程。通过用户输入凭证 → 服务器验证 → 确认身份 → 赋予账户权限这个验证流程,授予用户使用账户的权限,不涉及第三方令牌。

而授权则是将特定权限通过象征性令牌授予第三方。令牌可以是授权文件、授权码(token)等数字凭证,持有令牌者可执行超出原有权限的操作(比如上面表格中提到的管理员可以删帖,普通用户只能浏览)。在现代应用中,获取用户信息/操作数据等需要特定权限的场景需要授权。

登录是授权的前提:必须先确认用户身份(登录),才能基于身份分配权限(授权),二者的核心区别如下:

维度登录(认证)授权
作用阶段用户身份验证(入口关卡)资源访问控制(内部权限管理)
数据载体凭证:密码、生物特征、硬件密钥等权限声明:角色(Role)、策略(Policy)
技术实现Session/Cookie、JWT、OIDCRBAC、ABAC、OAuth Scope
失败响应401 Unauthorized(未认证)403 Forbidden(无权限)
生命周期短期(单次会话有效)长期(权限可能持久化存储)

接下来会详细介绍登录与授权的两种方式 —— Cookie 与 Authorization。其中,Cookie 的历史比较悠久,它起源于 Netscape 浏览器时代,解决电商网站本地存储(购物车)需求(非服务器存储)而产生;而 Authorization 是较新的标准,近年才开始流行。

2、Cookie

2.1 Cookie 的工作机制

Cookie 本质上是服务器要求客户端存储特定数据的机制,通过 Set-Cookie 头部实现指令传递。

以我们前面提到的购物车为例,用户增删商品后的结果需要展示在购物车中。比如先向购物车中添加一个苹果:

在这里插入图片描述

大致过程:

  • 那么客户端指定苹果数量为 1,并发送 POST 请求给服务器
  • 服务器收到请求后,需要让客户端,也就是浏览器保存苹果数量为 1 的信息,那么就通过 Set-Cookie: cart="apple=1" 让浏览器保存该购物车信息
  • 浏览器接收到 Set-Cookie,把 Set-Cookie 的内容与 Host 保存起来

随后再向购物车中添加一个香蕉:

在这里插入图片描述

大致过程:

  • 浏览器发送已经保存的 Cookie 内容 Cookie: cart="apple=1",并将本次新增的 banana=1 作为请求体传给服务器
  • 服务器接收后进行计算,计算出当前购物车内应该有苹果香蕉各一个,于是返回 Set-Cookie: cart="apple=1&banana=1" 让浏览器保存
  • 浏览器比对 Host 信息是 shop.com,就会更新 cart 的内容为 apple=1&banana=1

最后购物车要进行结算,发送结算请求时,Cookie 是上一步更新后的 Cookie: cart="apple=1&banana=1"

在这里插入图片描述

通过上例可以看出 Cookie 存储的特点:

  • 完全按服务器指令原样存储,不做任何解析或计算(如存 “apple=1” 就严格存该字符串)
  • 关联存储服务器域名或 IP,确保不同网站的 Cookie 不会混淆(访问 A 网站不会带上 B 网站的 Cookie)

2.2 Cookie 的作用

会话管理

上一节提到的购物车的例子其实就是 Cookie 进行会话管理的实例。此外,登录状态的管理也属于会话管理范畴。

在这里插入图片描述

在登录的过程中:

  • 客户端提交用户名密码(如 username=a&password=b)
  • 服务器验证通过后生成会话 ID(如 sessionid=123),并将这个会话 ID 通过 Set-Cookie 返回给客户端存储
  • 客户端在后续请求中,自动附带 Cookie 实现身份验证

客户端可以保存同一个服务器的多个不同名 Cookie,比如既可以保存 shop.com 的登录会话 ID(sessionid=123)又可以保存购物车信息(cart=“apple=1”),这称为多 Cookie 共存,客户端每次发送请求会带上 Cookie 的所有内容:

在这里插入图片描述

由于 HTTP 本身是无状态的,每个请求独立,服务器无法区分不同请求是否来自同一用户。通过 Session ID 给每个用户分配唯一标识符来解决这个问题,让服务器能跟踪用户状态,从而将 HTTP 无状态协议转为有状态。

个性化

比如访问一些网站时,可以选择一些主题啊等等的。那么在首次访问网站时,会被分配唯一的 Client ID,如 123:

在这里插入图片描述

然后在选择主题时(比如上面就选择了蓝色的 style),由于 Cookie 会带着 client_id 那么服务器就会存储该 client_id 的偏好设置,后续客户端再访问时会自动应用已存储的个性化设置。

用户行为追踪

通过 Cookie 追踪并分析用户行为,以便生成用户画像更好的推送广告以实现更大的商业利益。

大致的工作模式为:

  • 生成用户唯一标识:第三方统计代码嵌入多个网站(如 Google Analytics),在用户首次访问时,服务端生成唯一 ID(如 UUID)并存入 Cookie
  • 前端埋点采集行为数据:通过 JavaScript 监听用户操作(点击、滚动、页面跳转等),通过唯一 ID 跨站追踪用户访问路径(如从 shop.com 到 taobao.com)
  • 关联 User ID上报数据:每次事件触发时,携带 Cookie 中的 User ID 发送到服务端
  • 服务端存储与分析:接收数据并存储到数据库(如 MySQL、BigQuery)或日志系统(如 ELK),构建用户画像用于更精准的广告投放

技术关键:需要网站联盟共享数据才能建立完整用户画像。除此之外,利用 Cookie 追踪用户行为具有隐私争议:欧洲 GDPR 等法规要求必须明确告知用户(出现"本网站使用 Cookie"提示)。

2.3 跨站脚本攻击和跨站请求伪造

XSS(Cross-site scripting):跨站脚本攻击。即使⽤ JavaScript 拿到浏览器的 Cookie 之后,发送到⾃⼰的⽹站,以这种⽅式来盗取⽤户 Cookie。应对方式:服务器发送 Cookie 时,在敏感 Cookie 后面加上 HttpOnly,比如 Set-Cookie:session_id=123;HttpOnly 。这样 JS 就无法获取到 Cookie 信息从而避免 Cookie 信息泄露。

XSRF/CSRF(Cross-site request forgery):跨站请求伪造。指用户在不知情的情况下访问了保存 Cookie 的网站,然后越权操作用户的账户。比如诱导用户访问恶意链接自动发起请求(如 bank.com/transfer?to=badguy&amount=1000000,向 badguy 账户转账一百万)。

具体的攻击流程:

  1. 用户登录合法网站(如银行):浏览器保存了会话 Cookie(如 sessionid=abc123
  2. 用户访问恶意页面:攻击者构造的链接、钓鱼邮件或第三方网站
  3. 触发恶意请求:恶意页面自动发送请求到合法网站,携带用户的 Cookie
  4. 服务器执行操作:服务器验证 Cookie 有效,误认为用户主动操作

主要防御机制:

  • CSRF Token:服务器生成唯一 Token,嵌入表单或请求头,验证请求合法性
  • 校验 Referer 头部识别请求来源是否在白名单内
  • 关键操作要求二次认证(如短信验证码)

3、Authorization

Cookie 在移动端逐渐被 Authorization 机制取代了,因为 Cookie 作为浏览器自动管理的本地存储机制,存在很严重的局限性:

  • 跨域限制:受同源策略(Same-Origin Policy)约束,跨域请求需复杂配置(如 CORS)
  • 安全隐患:易受 CSRF(跨站请求伪造)攻击,浏览器自动携带 Cookie 的特性可能被恶意利用
  • 状态依赖:服务端需维护会话状态(Session),导致分布式系统中扩展困难(需共享 Session 存储)
  • 移动端兼容性差:原生 App 或第三方服务难以直接使用 Cookie 机制

Cookie 在移动端的取代在登录验证场景表现的尤为明显,因为 Authorization 被设计出来就是为了做登录和授权的。下面会介绍 Authorization 的两种主流方式 —— Basic Token 与 Bearer Token。

3.1 Basic Token

Basic 方式的格式为:Authorization: Basic <username:password(Base64ed)>。比如我在某个网站上的用户名是 Tony,密码是 123456,那么按照上面的格式,先对 Tony:123456 取一次 Base64 编码,结果是 VG9ueToxMjM0NTY=。那么在发送网络请求时,给请求头中添加 Authorization: Basic VG9ueToxMjM0NTY= 即可完成需要授权的操作。但假如你提供的用户名密码转成的 Base64 不正确,服务器就会返回 401 提示你未授权。

按照如上格式发送给服务器经过 Base64 编码过的用户名和密码,理论上来说,这种方式有安全风险,因为 Base64 是可逆解码,一旦请求被截获,第三方可以通过还原 Base64 信息的方式拿到你的用户名和密码。不过配合 HTTPS 使用可以解决该问题,因为即便被截获,第三方也看不到明文信息,也就不用说破解了。

3.2 Bearer Token

bear 在这里的意思是拿着、持有,那么 bearer 就引申为拿着权限的人。意思是如果想做一些事情,但是没有权限,可以向有权限的 bearer 获取权限之后再做事。本质上是将原始权限持有者的权限临时转移给持票人使用。

Bearer 的格式为:Authorization: Bearer <bearer token>,bearer token 是授权方提供的,而不是像 Basic Token 那样在本地自己计算出来的。

Bearer Token 与 Basic Token 的主要区别:

Basic TokenBearer Token
生成方式通过计算得到(用户名+冒号+密码进行Base64编码)由授权方直接发放,无法自行计算生成
获取途径本地即可生成必须向授权方申请获取
使用场景用于基础身份验证用于授权流程,通常通过 OAuth 协议获取

获取 Bearer Token 的主要方式是通过 OAuth2.0 协议,下面来介绍详细流程。

3.3 OAuth2 协议

OAuth 2.0 的优势有:

  • 减少开发者工作量
  • 降低关注点复杂度
  • 同时保持授权流程的安全性

授权流程需要与授权服务器交互完成,客户端无法自行生成。

第三方登录流程

我们先以在 PC 浏览器中通过 GitHub 登录 CSDN 的过程说明 OAuth2 的授权流程。

在 CSDN 的登录页面点击 GitHub 图标即开始了第三方登录的流程:

请添加图片描述

点击 GitHub 图标后,会弹出如下的授权页面,该授权页面弹出意味着开始了第三方授权流程,也就是 OAuth2 的流程:

请添加图片描述

这是第三方授权页面,目的是把获取 GitHub 公共数据的权限授予 CSDN。在这个第三方授权的过程中,第三方是你要登录的、被授予权限的平台,也就是 CSDN。

区分第三方登录与第三方授权的概念。

从技术上来讲,只有第三方授权这个概念。第三方登录是产品角度的说法,而且它最初是国外流行的概念叫 Social Login,是使用社交网络进行登录。传入中国后为了便于用户理解才称为“第三方登录”。

在第三方登录过程中,GitHub 是第三方,但是在第三方授权的过程中,即上面这个授权页面的所做的工作中,第三方是获取权限、想要登录的 CSDN 平台。

注意看网页地址的 client_id 实际上是 GitHub 为 CSDN 分配的 ID,这是 CSDN 在向 GitHub 申请获取 OAuth 授权资质,提供网站的地址、名称、图标之后,由 GitHub 审核通过之后给申请者分配的 ID。当用户在 CSDN 上申请通过 GitHub 进行授权时,CSDN 要把 client_id 传给 GitHub,然后在这个授权页面 GitHub 就会展示该 client_id 在申请授权资质时提供的相关信息(地址、名称、图标等)供用户判断,用户在确认信息无误(没有进行错误授权给其他网站)的情况下才会点击授权按钮。

点击授权按钮后,CSDN 就有权限使用 GitHub 上的公开信息,比如你在 Github 上的用户名、头像等数据。用这些信息创建(未使用该信息创建过账号的情况下)/ 登录(已用该信息创建过账号)本地账号。

具体说来,点击授权按钮后,GitHub 会返回给授权过程的第三方 —— CSDN 一个 Authorization code 用于获取 token:

在这里插入图片描述

这一步没有直接传 token 的原因有二:

  • OAuth2 标准(RFC 6749)没有在技术实现层面强制要求所有实现必须用 HTTPS,但在标准文档和主流实现、最佳实践中,强烈建议并默认所有 OAuth2 通信必须通过 HTTPS 进行。因此直接传 token 是有被截获的可能性的
  • 浏览器以及电脑都有被 hack 的可能性,token 保存在本地也有被窃取的可能,并不安全

因此,GitHub 只给 CSDN 发送一个 Authorization code,CSDN 再把这个 Authorization code 转发给它的服务器:

在这里插入图片描述

由 CSDN 的服务器向 GitHub 发送 Authorization code 以及 client_secret。client_secret 也是 CSDN 向 GitHub 申请授权资质时 GitHub 发给 CSDN 的,需要严格保密。因此 client_secret 只可保存在服务器上,且这一步发送一定要使用 HTTPS 避免 client_secret 被窃取:

在这里插入图片描述

最后 GitHub 验证 client_secret 正确便会把 access token 发送给 CSDN 的服务器。到这里,OAuth2 的授权过程就结束了。

第三方授权过程结束,但第三方登录过程还没完。接下来,CSDN 的 Server 会带着刚刚拿到的 access token 向 GitHub 发送一个请求报文,以获取刚刚被授权获取的公开信息(账户名、头像等):

在这里插入图片描述

拿到这些信息后就注册 CSDN 账号并进行登录,将登录成功的信息返回给浏览器显示,登录过程就完成了。

用户感知的是"用 GitHub 账号登录",实际是授权 + 信息获取 + 本地登录的组合流程。

以上是标准的第三方登录与授权流程,但有一些公司处于某些目的,会在拿到 access token 之后发送给浏览器将其保存在本地,让浏览器带着 access token 向 GitHub 进行后续的请求,这样还是会面临浏览器以及电脑本身被 hack 导致 token 被盗的安全隐患。

微信登录

在移动应用中使用微信进行第三方登录走的实际上也是一个完整的 OAuth2 授权流程。当你在想要登录的应用中点击微信登录选项时:

  • 应用调用微信 API 跳转至微信授权页面
  • 显示应用信息(名称 & 图标)来自微信服务器验证,开发者无法篡改显示内容,防止欺骗用户
  • 用户确认"授权使用微信账户信息登录",实际是授权第三方应用通过微信身份系统完成认证
  • 用户确认后,微信服务器生成授权码(authorization code)
  • 微信客户端关闭授权页,携带授权码跳回原应用
  • 应用客户端将授权码发送给自身服务器
  • 应用服务器用授权码 + secret 向微信服务器换取 access token
  • 再用 access token 获取用户微信资料(ID/昵称/头像等)
  • 使用用户微信资料完成注册/登录

3.4 Refresh Token

有时授权服务器不止返回 access token,还会返回 refresh token,大致格式如下:

{
	"token_type": "Bearer",
 	"access_token": "xxxxx",
 	"refresh_token": "xxxxx",
 	"expires_time": "xxxxx"
 }

access token 用于获取用户信息,而 refresh token 用于在 access token 过期后获取新的 access token:

请添加图片描述

当然,除了过期,也有另一种情况就是 access token 由于某些情况被坏人窃取了,此时你需要废掉原来的 access token,那么你可以向授权服务器发送 refresh token 在拿到新的 access token 的同时让原本被窃取的 access token 作废。这样可以避免重新走有些麻烦的 OAuth2 授权流程造成用户流失。

最后看看 access token 与 refresh token 的区别与联系:

Token 类型作用生命周期安全性要求
Access Token访问资源的短期凭证,客户端将其附加到请求头中访问受保护的 API/资源。短(如 1 小时)较高(需加密传输)
Refresh Token用于获取新的 Access Token 的长期凭证,避免用户频繁重新登录。长(如 7 天)极高(需安全存储)

两种 token 协同工作:

  1. 用户登录:客户端通过认证后,授权服务器同时返回 access_tokenrefresh_token
  2. 访问资源:客户端使用 access_token 访问 API。
  3. Token 过期:当 access_token 失效(HTTP 401 错误),客户端用 refresh_token 向授权服务器请求新的 access_token
  4. 刷新令牌:授权服务器验证 refresh_token 有效性,颁发新的 access_token(可能返回新 refresh_token,取决于策略)。

4、总结

Cookie 机制:

  • 本质:一种客户端存储机制,允许服务端通过浏览器/手机软件在客户端保存指定内容
  • 工作方式:服务端发送指令让客户端存储数据,后续请求时客户端自动携带该数据
  • 原始用途:主要用于服务端希望保存但不想自行存储的数据
  • 延伸应用:被广泛用于存储用户登录信息(非最初设计目的)

Authorization Header

  • 专业用途:专门用于授权验证的 HTTP 头部
  • 两种主流模式:
    • Basic Token:使用"用户名:密码"格式进行 Base64 编码的直接授权方式
    • Bearer Token:采用持票人模式的令牌验证方式

Token 应用场景

  • OAuth2 流程:Bearer Token 的典型实现方案
  • 自研登录系统:
    • 可借鉴 OAuth2 的 Bearer Token 形式(非模仿而是形式相似)
    • 本质区别:自研系统的 token 由自家服务器签发,但验证流程类似
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值