认证对象
在提到认证的场景下,会见到这三个名词,意思差不多:
- Identity:账户 Account / User
- Principal
- Subject
认证要素 Authentication Factors
本质就是用户可以提供的仅自己知道的东西,按照维基百科 Multi-factor authentication 词条分成四类:
-
Knowledge(我知道的)
- 密码
- Secret:密码是给人使用的,而 Secret 是给程序使用的,一般都比较长。
-
PIN (Personal identification number)
PIN 是通过绑定设备的方式实现身份认证的弱密码,且通过一些系统规则进行约束(输入间隔、错误次数)。
因为获取到设备就是一道门槛,所以 PIN 码不要求强度,一般就是 4 ~ 8 位数字。- 信用卡
- SIM 卡(PIN 码 / PUK 码(PIN Unlock))
- Windows 登录(主板 TPM 安全芯片 / OS 软件支持)
PIN 是“用系统规则兜底的弱密码”,而 Password 是“靠自身强度站住的凭证”。
-
Possession(我拥有的)
-
证书(X.509 Certificate):
证书的主要用途(这里就是指第二种用途):
- 网络通讯安全(TLS):SMTPS / HTTPS...
- 网络通讯身份认证:客户端证书
- 签名:安装包签名、文档签名、邮件签名
-
硬件令牌:SIM 卡 / NFC 卡 / 板载 TPM / USB Key(U 盾) / 动态口令
- 软件令牌:OTP
-
-
Inherent(我的特征)
- 生物识别技术:人脸识别、指纹识别、声纹识别、虹膜识别、静脉识别
PS:腾讯刷掌支付就是利用掌纹 + 掌静脉进行身份识别。
- 生物识别技术:人脸识别、指纹识别、声纹识别、虹膜识别、静脉识别
-
Location
- 特定网络(VPN、特定 IP 地址)
- 特定设备(浏览器指纹、设备指纹)
- 特定时间段
- 特定地理位置
程序常用的认证方法
基于长连接的服务,连接建立之后立即认证,后续的所有请求都是认证状态。
基于短链接的服务有 3 种方式:
- 每次提供认证要素
- 认证获取身份标识,后续每次请求提供身份标识
- 认证对象标识 + 请求签名
认证方法
密码
风险点与应对方法:
-
内部人员可直接获取用户密码 / 数据库泄漏即密码泄漏
- 风险描述:若存储明文或可逆形式,任何拥有数据库、日志、备份访问权限的人都可直接获取用户密码
该风险一旦发生,影响是不可控且不可逆的 - 处理办法:服务器存储不可逆的密码派生结果(哈希),服务器自身都无法获取密码原文,杜绝通过缓存、日志等泄漏的可能性,即便数据库泄漏也不会泄漏密码
- 风险描述:若存储明文或可逆形式,任何拥有数据库、日志、备份访问权限的人都可直接获取用户密码
-
认证过程中密码在网络传输中被窃听
- 风险描述:明文或弱加密传输可被被动监听、证书伪造或降级攻击可导致中间人攻击
- 应对方法:使用 TLS 加密传输认证数据、禁止明文或非加密通道进行认证、防止协议降级
-
哈希值被预计算攻击(彩虹表)快速破解(对第一点的补充)
- 风险描述:无盐哈希可被彩虹表快速反查,相同密码在数据库中呈现相同哈希,便于批量分析
- 应对方法:为每个用户引入独立随机盐值,将盐与密码共同参与哈希计算,使预计算攻击在经济上不可行
-
数据库泄露后遭遇离线暴力破解
- 风险描述:攻击者可在无速率限制条件下无限次尝试密码、弱哈希算法会导致破解成本极低
- 应对方法:使用高计算成本的密码派生算法,通过多轮迭代或内存硬化显著提高单次尝试成本,将攻击从“可规模化”转为“高成本个案攻击”
-
在线暴力破解登录接口
- 风险描述:攻击者通过接口持续尝试密码,即使数据库安全,接口仍可能成为突破口
- 应对方法:登录失败限速,连续失败触发冷却或阻断,增加人机校验或额外验证步骤
-
弱密码 / 常用密码
- 风险描述:
- 应对方法:提升密码最低复杂度或长度要求
-
凭证填充攻击(使用其他系统泄露的账号密码)
风险描述:攻击者使用已泄露的用户名/密码组合进行自动化登录,与本系统密码算法强弱无直接关系
应对方法:登录行为异常检测,对高风险登录触发额外验证,另外引入多因素认证降低单一密码的安全权重 -
认证请求被重放(Replay Attack)
-
方法 1: 服务器存储明文、客户端提交明文(Base64 也是明文)、服务器进行字符串对比
存在的问题:1. 数据库泄露即密码泄露;2. 内部人员可窥探密码;3. 传输过程易被窃听 - 方法 2: 服务器存储两次哈希(如 MD5)值、客户端提交密码哈希值、服务器进行哈希之后和存储值进行字符串对比
存在的问题:1. “哈希”成为等效密码,泄露哈希值即可直接登录;2. 无法抵御彩虹表攻击 - 方法 3:方法 2 改进版本,服务器为每个账户生成盐值(Salt),然后在第二次哈希进行加盐,可以抵御彩虹表攻击
- 方法 4:服务器存储哈希值、客户端提交明文、服务器进行哈希之后和存储值进行字符串对比
存在的问题: 如果哈希算法(如 MD5、SHA-256)不够安全,仍存在易受彩虹表和暴力破解的风险 - 方法 5:方法 4 改进版本,服务器为每个账户生成盐值(Salt),然后进行加盐哈希
Challenge-Response
- 客户端发起认证
- 服务器发起挑战:提供一个随机数(称为 Challenge,即挑战值)。
- 客户端生成应答:将用户口令(或密钥)与收到的挑战值结合,使用一个预定的单向哈希函数(如 MD5)进行计算,生成一个应答值(Response)。
- 服务器验证应答:使用存储在服务器上的用户口令和相同的算法进行运算,并将自己计算的结果与客户端返回的应答值进行比较。
- 如果两者一致,则认证通过;否则,认证失败,客户端需要重新发起认证。
提交认证要素的方式
- TCP 协议中自定义包结构
- HTTP 协议
- 请求头
- HTTP authentication(
Authorization: Basic Base64(username ":" password))
- HTTP authentication(
- URL 参数(容易被日志记录或者被代理服务器获取,不建议使用)
- 请求体
- 请求头
- SMTP 协议
- Login,分别提供用户名 Base64 字符串和密码 Base64 字符串。
- Plain,明文传输
\0username\0password。
实践:
- 确保
- 使用 Hash 传输
Challenge-Response
认证流程
- 每次提供认证要素
- 认证获取身份标识,后续每次请求提供身份标识
- 认证对象标识 + 请求签名
用户名 + 密码
-
HTTP 认证
Authorization: Basic Base64(username + password)客户端将用户名和密码用冒号连接后进行 Base64 编码,放在 Authorization 请求头中。虽然实现简单,但安全性较低,除非在 HTTPS 上使用,否则凭证容易被拦截。
-
HTTP Cookie / Session
通过认证 URL 完成认证之后,服务器提供一个认证标识,客户端自行存储,并在后续的请求中始终带上。
比如浏览器,可以将认证标识存储在 Cookie 中,LocalStorage、SessionStorage、IndexedDB。PS:基于 SQLite 的 Web SQL Database 已被废弃。
比如移动端,可以将认证信息存储在本地存储或安全的密钥库中。客户端给服务器端发送数据的方式不外乎就这三种:请求头、URL 参数、请求体。
其中,浏览器 Cookie 自动随请求发送给服务器就是夹在请求头中传递的。服务器将 SessionID 标记为认证通过,后续通过 Cookie 中的 SessionID 来验证用户身份。
-
SMTP 认证
- Login,分别提供用户名 Base64 字符串和密码 Base64 字符串。
- Plain,明文传输
\0username\0password。
API Key
API Key 是一种简单的认证方式,通常作为请求头或 URL 参数传递。
# 作为请求头传递
Authorization: ApiKey abcdef123456
# OR
X-API-Key: abcdef123456
# 或作为URL参数(可能会被代理获取,或者服务器日志记录,非常糟糕)
https://api.example.com/data?api_key=your_api_key_here
生产环境需要:
- 必须使用 HTTPS
- 尽可能控制权限范围
- 实现定期轮换
Access Key ID + Access Key Secret
Authorization: ApiKey ak_123456:sk_xxxxx
# OR
X-API-Key-Id: ak_123456
X-API-Key: sk_xxxxx
API Key + Timestamp + Nonce + Signature
放在 HTTP Header 中比放在 Body 中好,为了实现认证需要解析 Body 的业务数据就比较不换算。
X-Api-Key: ak_123456
X-Timestamp: 1700000000 # 防重放
X-Nonce: randomStr # 不可抵赖(客户端生成)
X-Signature: hmac_sha256(sk_xxxxx, canonical_request)
签名内容(canonical_request):
HTTP_METHOD
PATH
QUERY
BODY_HASH
TIMESTAMP
NONCE
Token / JWT
通过单独的认证方法之后,服务器提供一个认证标识
JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间安全传输信息作为 JSON 对象。
JWT 由三部分组成,格式为 Header.Payload.Signature:
// JWT结构示例
const header = {
alg: "HS256", // 签名算法
typ: "JWT", // 令牌类型
};
const payload = {
sub: "1234567890", // 主题(用户ID)
name: "John Doe", // 自定义声明
admin: true,
iat: 1516239022, // 签发时间
exp: 1516247022, // 过期时间
};
// 签名部分
const signature = HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret);
优势:
- 无状态:服务器不需要存储会话信息
- 可扩展:可以在 payload 中存储自定义信息
- 跨域支持:适合分布式系统
使用场景:
- 单点登录(SSO)
- API 认证
- 信息交换
高级认证方案
OAuth
SSO
MFA 多因素认证
关键步骤需要结合多种认证因素提高安全性:
生物特征:指纹、人脸识别
Possession:手机验证码、OTP
Token 访问凭证
Bearer Token
PoP (Proof-ofPossession Token)
Access Token / Refresh Token
Hash:哈希函数/哈希算法/哈希运算,通过算法将任意长度的输入映射成固定长度的输出
Cryptographic Hash: 加密哈希,满足密码学安全的哈希算法/哈希运算(不要被名字误导,并没有做加密)。
首先,就要是一个优秀的哈希算法:任何 hash 值出现的概率是相等的
其次,就是要抗攻击,具体满足以下三个要求:
- 原像抗性(Preimage Resistance):不能反推输入(
2^n) - 第二原像抗性(Second Preimage Resistance):不能替换等价消息(
2^n) - 碰撞抗性(Collision Resistance):不能制造任意碰撞(
2^(n/2))
参考维基百科: 加密哈希函数、Cryptographic hash function。
这些密码学的知识点我没有看明白。
A cryptographic hash function (CHF) is a hash algorithm (a map of an arbitrary binary string to a binary string with a fixed size of n bits) that has special properties desirable for a cryptographic application:
- the probability of a particular n-bit output result (hash value) for a random input string ("message") is $2^{-n}$ (as for any good hash), so the hash value can be used as a representative of the message;
- finding an input string that matches a given hash value (a pre-image) is infeasible, assuming all input strings are equally likely. The resistance to such search is quantified as security strength: a cryptographic hash with n bits of hash value is expected to have a preimage resistance strength of n bits, unless the space of possible input values is significantly smaller than $2^n$ (a practical example can be found in Attacks on hashed passwords);
- a second preimage resistance strength, with the same expectations, refers to a similar problem of finding a second message that matches the given hash value when one message is already known;
- finding any pair of different messages that yield the same hash value (a collision) is also infeasible: a cryptographic hash is expected to have a collision resistance strength of n/2 bits (lower because of the birthday paradox).
加密哈希
MAC / HMAC:对称签名
Digital Signature 非对称加密算法签名
Cononical Request 规范化请求字符串,签名数据的统一格式
安全
Replay Attack 重放攻击
MITM 中间人攻击(相关名词:Request Integrity 请求未被篡改)
Session Fixation 会话劫持攻击
CSRF: Cross Site Request F 跨站点请求伪造
CSS: Cross Site Scripting 跨站点脚本攻击
Transport Security(TLS:Transport Layer Security)
Session (服务器端)会话
Stateless Authentication:Token 自验证,好处是实现简单、容易拓展,缺点是可控性降低,不能实现下线、登录设备数要求
权限控制
IAM
RBAC
ABAC
Scope
Least Privilege
Key Rotation 定期轮换
Key Revocation 及时吊销
Key Versioning 平滑升级
Zero Trust 零信任,不信任所有请求
Defense in Depth 多层防护
SOC2 SaaS 安全合规
ISO 27001 信息安全管理体系