Appearance
本模块聚焦身份认证与权限控制相关的安全问题,涵盖 JWT、OAuth 2.0、SSO、密码存储、权限绕过、Session 安全、API 安全等核心主题。是后端开发和安全工程师面试的重点内容。
Q1: JWT的工作原理?有哪些安全问题? 「🟡 中级」
考察点:考察 JWT 认证机制的理解深度。筛掉只会用库、不了解底层原理和安全风险的开发人员。
参考答案:
JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间安全地传输信息。信息被编码为 JSON 对象,通过数字签名验证其完整性和真实性。
JWT 结构:
JWT 由三部分组成,用点号 . 分隔:Header.Payload.Signature
Header(头部)
json{ "alg": "HS256", // 签名算法 "typ": "JWT" // 令牌类型 }Base64URL 编码后形成第一部分。
Payload(载荷)
- 存放声明(Claims),如用户ID、角色、过期时间等
- 标准声明:
iss(签发者)、exp(过期时间)、sub(主题)、aud(受众)等 - 注意:Payload 只是 Base64 编码,不是加密,任何人都可以解码读取
Signature(签名)
- 使用 Header 中指定的算法,对
base64UrlEncode(header) + "." + base64UrlEncode(payload)进行签名 - 密钥只有服务端知道,用于验证 Token 是否被篡改
- HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
- 使用 Header 中指定的算法,对
工作流程:
用户登录 → 服务端验证密码 → 生成 JWT → 返回给客户端
客户端存储 JWT(localStorage/Cookie)
后续请求在 Authorization 头中携带:Bearer <token>
服务端验证签名 → 解析 Payload → 获取用户信息常见安全问题:
None 算法攻击
- 将 Header 中的
alg改为none,某些 JWT 库会接受无签名的 Token - 攻击者可以任意伪造 Payload
- 将 Header 中的
密钥爆破(弱密钥)
- 使用 HMAC 算法时,如果密钥强度不够,可以被暴力破解
- 破解后可伪造任意 Token
算法混淆攻击(Alg 切换)
- 将 RS256(非对称)改为 HS256(对称),用公钥作为密钥进行签名
- 如果服务端未校验算法类型,可能被绕过
敏感信息泄露
- Payload 只是 Base64 编码,不应存放密码、身份证号等敏感信息
过期管理不当
- Token 过期时间设置过长,被盗后可长期使用
- 缺少 Token 撤销机制(JWT 是无状态的,服务端无法主动作废)
存储安全问题
- 存在 localStorage 中,易受 XSS 攻击窃取
- 存在 Cookie 中,易受 CSRF 攻击(需设置 SameSite)
最佳实践:
- 使用强密钥(HMAC)或非对称加密(RS256/ES256)
- 设置合理的过期时间(access token 短时效 + refresh token 机制)
- 验证时强制指定算法,不依赖 Token 中的 alg 字段
- Payload 不存放敏感信息
- 敏感操作进行二次验证
- 实现 Token 黑名单/撤销机制(Redis 存储已撤销 Token)
追问延伸:
- JWT 和 Session 有什么区别?各自的优缺点?
- JWT 如何实现踢人下线/单点登出?
- Refresh Token 的安全注意事项有哪些?
- JWT 放在 Cookie 和放在 Authorization 头各有什么安全风险?
- 什么是 JWT 的重放攻击?如何防范?
Q2: OAuth 2.0 的流程是什么?有几种授权模式? 「🟡 中级」
考察点:考察对授权协议的理解。筛掉不了解第三方登录原理、对授权和认证概念混淆的开发人员。
参考答案:
OAuth 2.0 是一个授权框架,允许第三方应用在用户授权的前提下,访问用户在某个服务上的资源,而不需要获取用户的账号密码。
四种角色:
- Resource Owner(资源所有者):用户
- Client(客户端):第三方应用
- Authorization Server(授权服务器):颁发令牌的服务器
- Resource Server(资源服务器):存放受保护资源的服务器
四种授权模式:
授权码模式(Authorization Code Grant) - 最安全、最常用
- 适用于有后端的 Web 应用
- 流程最完整,Token 不经过浏览器
隐式模式(Implicit Grant) - 已不推荐使用
- 适用于纯前端应用(SPA)
- 直接返回 Access Token,安全性较低
- OAuth 2.1 中已被移除,推荐使用授权码 + PKCE
密码模式(Resource Owner Password Credentials Grant)
- 用户直接将用户名密码交给第三方应用
- 适用于高度信任的内部系统
- 安全风险高,不推荐外部使用
客户端凭证模式(Client Credentials Grant)
- 适用于服务器之间的通信,没有用户参与
- 客户端使用自己的凭证获取 Token
授权码模式详细流程:
1. 用户点击"使用微信登录"
↓
2. 客户端跳转到授权服务器的授权页面
GET /authorize?response_type=code&client_id=xxx&redirect_uri=xxx&scope=xxx
↓
3. 用户登录并授权
↓
4. 授权服务器重定向回客户端,携带授权码 code
redirect_uri?code=AUTHORIZATION_CODE
↓
5. 客户端后端使用 code 向授权服务器换取 Access Token
POST /token
grant_type=authorization_code
code=AUTHORIZATION_CODE
redirect_uri=xxx
client_id=xxx
client_secret=xxx
↓
6. 授权服务器返回 Access Token(和 Refresh Token)
{ "access_token": "...", "token_type": "bearer", "expires_in": 3600 }
↓
7. 客户端使用 Access Token 访问资源服务器PKCE(Proof Key for Code Exchange):
- 为授权码模式增加的安全增强,主要用于移动端和 SPA
- 客户端生成随机
code_verifier,计算其哈希code_challenge - 授权时发送
code_challenge,换取 Token 时发送code_verifier - 防止授权码被拦截后滥用
安全注意事项:
redirect_uri必须在服务端白名单校验,防止开放重定向state参数防止 CSRF 攻击client_secret不能泄露到前端- Access Token 设置较短的过期时间
- 使用 HTTPS 传输
追问延伸:
- OAuth 2.0 和 OpenID Connect(OIDC)有什么关系?OIDC 增加了什么?
- 什么是开放重定向漏洞?如何利用?
- 授权码模式为什么比密码模式更安全?
- OAuth 2.0 的 state 参数有什么作用?
- 什么是 Token 泄露?如何防范?
Q3: 什么是SSO单点登录?实现原理? 「🟡 中级」
考察点:考察统一认证体系的理解。筛掉对多系统认证架构无概念的开发人员。
参考答案:
SSO(Single Sign-On,单点登录)是指在多个应用系统中,用户只需要登录一次,就可以访问所有相互信任的应用系统。
经典实现:CAS 流程(Central Authentication Service)
用户访问 App A(未登录)
↓
App A 重定向到 CAS 认证中心(携带 service 参数)
↓
CAS 认证中心检测到用户未登录,显示登录页面
↓
用户输入账号密码登录
↓
CAS 认证中心生成全局会话(Cookie: TGC)
↓
CAS 重定向回 App A,携带 Ticket(ST)
↓
App A 后端拿着 ST 到 CAS 验证
↓
CAS 验证通过,返回用户信息
↓
App A 创建局部会话,用户登录成功
用户访问 App B(未登录)
↓
App B 重定向到 CAS 认证中心
↓
CAS 检测到 TGC Cookie(已登录),直接生成 ST
↓
CAS 重定向回 App B,携带 ST
↓
App B 验证 ST,创建局部会话SSO 的实现方式:
同域 SSO
- 所有应用在同一个父域名下(如 a.example.com、b.example.com)
- 将 Cookie 设置在父域
.example.com上,所有子域共享 - 实现简单,但只适用于同根域名
跨域 SSO
- 应用分布在不同域名下
- 需要一个独立的认证中心(CAS、OAuth、SAML 等方式)
- 通过重定向传递登录状态
基于 OAuth 2.0 / OpenID Connect 的 SSO
- 认证中心作为 OAuth 授权服务器
- 各业务系统作为 OAuth 客户端
- 用户在认证中心登录后,各系统通过授权码获取用户信息
基于 SAML 的 SSO
- 企业级应用常用,尤其传统企业软件
- 使用 XML 格式传递认证信息
- 常见于 Microsoft AD FS 等场景
SSO 登出(单点登出 SLO):
- 用户在一个系统登出时,通知所有其他系统也登出
- 实现方式:后端通知、前端 iframe 逐个调用登出接口
追问延伸:
- SSO 和 OAuth 有什么区别和联系?
- CAS 中的 TGT 和 ST 分别是什么?有什么区别?
- 跨域 SSO 中,如何解决 Cookie 跨域问题?
- 单点登出如何实现?有哪些难点?
- JWT 可以用来实现 SSO 吗?如何实现?
Q4: 密码应该如何安全存储? 「🟢 校招/初级」
考察点:考察安全基础知识。筛掉还在用明文或简单 MD5 存密码的初级开发。
参考答案:
密码存储的核心原则是:永远不要明文存储密码,也不要用可逆加密存储密码。
存储方案演进:
明文存储 - 完全不可接受
- 数据库泄露 = 所有密码泄露
简单哈希(MD5/SHA1) - 不安全
- 相同密码哈希值相同,可以通过彩虹表反查
- 速度快,暴力破解效率高
加盐哈希(Salted Hash) - 基础安全
- 每个用户生成一个随机盐值(salt)
- 存储:
hash(password + salt)和salt - 相同密码因为盐不同,哈希结果不同
- 问题:普通哈希算法(SHA-256)计算太快,GPU 每秒可计算数十亿次
慢哈希算法 - 当前推荐
- 故意设计成计算缓慢,增加暴力破解成本
- 常见算法:bcrypt、scrypt、Argon2
推荐算法:
| 算法 | 特点 | 推荐度 |
|---|---|---|
| Argon2 | 最新,内存硬度高,抗 GPU 攻击 | ⭐⭐⭐⭐⭐ |
| scrypt | 内存和计算双重硬度 | ⭐⭐⭐⭐ |
| bcrypt | 经过长期验证,广泛使用 | ⭐⭐⭐⭐ |
| PBKDF2 | 基于 SHA 系列,可配置迭代次数 | ⭐⭐⭐ |
bcrypt 示例:
密码: mypassword123
盐值: $2a$10$N9qo8uLOickgx2ZMRZoMye
哈希: $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy$2a$:算法标识10$:工作因子(2^10 = 1024 次迭代)- 盐和哈希结果存储在同一个字符串中
密码策略最佳实践:
- 密码最小长度(建议 8 位以上,越长越好)
- 复杂度要求(大小写、数字、特殊字符组合)
- 禁止使用常见弱密码(如 123456、password、qwerty 等)
- 定期更换密码(企业场景)
- 登录失败次数限制 + 验证码(防暴力破解)
- 支持多因素认证(MFA/2FA)
追问延伸:
- 加盐哈希和慢哈希有什么区别?为什么慢哈希更安全?
- bcrypt 的工作因子(cost factor)是什么意思?如何选择?
- 什么是彩虹表攻击?加盐为什么能防御彩虹表?
- 如果数据库被拖库了,攻击者如何破解密码?
- 密码重置功能有什么安全风险?
Q5: 什么是权限绕过?常见方式有哪些? 「🔴 高级」
考察点:考察访问控制安全的深度。筛掉只做了前端鉴权、后端权限设计混乱的开发人员。
参考答案:
权限绕过是指攻击者通过各种手段,访问或操作其权限范围之外的资源或功能。本质是访问控制(Access Control)机制存在缺陷。
常见类型:
水平越权(IDOR - Insecure Direct Object Reference)
- 相同角色的用户之间,互相访问对方的数据
- 示例:用户 A 可以通过修改 URL 中的
user_id=123访问用户 B 的订单 - 原因:只验证了用户是否登录,没有验证数据归属权
垂直越权(Privilege Escalation)
- 低权限用户访问高权限功能
- 示例:普通用户通过构造请求访问管理员接口
/admin/deleteUser - 原因:缺少角色权限校验,或前端隐藏但后端未校验
未授权访问
- 完全不需要登录就能访问本应受保护的资源
- 示例:直接访问后台管理页面、API 接口无需认证
- 原因:缺少认证中间件,或配置错误
常见绕过方式:
URL 参数篡改
- 修改
id、user_id、order_id等参数访问他人数据 - 遍历 ID(如 id=1,2,3...)批量获取数据
- 修改
HTTP 方法绕过
- 接口只校验了 GET,POST/PUT/DELETE 没校验
- 使用 OPTIONS、HEAD 等方法绕过
路径绕过
/admin/user被拦截,但/admin/./user、/admin/../admin/user可以绕过- URL 编码绕过:
/%61dmin/user
请求头绕过
- 修改
X-Forwarded-For为 127.0.0.1 绕过 IP 白名单 - 添加
X-Original-URL、X-Rewrite-URL头绕过路径控制
- 修改
接口参数污染
- 同时传
user_id=1&user_id=2,校验的是第一个,实际用的是第二个
- 同时传
前端绕过
- 前端隐藏了按钮/菜单,但直接构造请求仍能调用后端接口
- 前端校验了权限,但后端没有校验
防御方案:
- 统一鉴权中间件:所有请求经过统一的认证和授权中间件
- 基于上下文的数据权限:查询数据时从 Session/JWT 中获取用户ID,而不是从请求参数中获取
- 权限校验框架:使用 Spring Security、Shiro、Casbin 等成熟框架
- RBAC/ABAC 权限模型:
- RBAC(基于角色):用户 → 角色 → 权限
- ABAC(基于属性):更灵活的细粒度权限控制
- 接口安全测试:越权测试是安全测试的必测项
- 默认拒绝:白名单机制,默认所有接口需要认证,只放行公开接口
追问延伸:
- 什么是 IDOR?举一个你遇到过的真实案例。
- RBAC 和 ABAC 有什么区别?各自适用场景?
- 如何设计一个通用的数据权限系统?
- 微服务架构下如何做统一鉴权?
- 什么是权限提升漏洞?和越权有什么区别?
Q6: Session安全有哪些注意事项? 「🟡 中级」
考察点:考察会话安全的全面理解。筛掉对 Session 安全细节不了解、Cookie 配置随意的开发人员。
参考答案:
Session 是服务端维护用户登录状态的机制,通过 Session ID 识别用户。Session 安全的核心是保护 Session ID 不被窃取和伪造。
主要安全威胁:
Session 劫持(Session Hijacking)
- 攻击者获取到用户的 Session ID,冒充用户登录
- 获取方式:XSS 窃取、网络窃听、URL 泄露、浏览器历史等
Session 固定(Session Fixation)
- 攻击者先获取一个 Session ID,诱导用户使用该 ID 登录
- 用户登录后,攻击者使用相同的 Session ID 即可冒充用户
- 常见场景:Session ID 通过 URL 传递,攻击者构造带 Session 的链接
Session 泄露
- URL 中包含 Session ID(如 PHPSESSID 在 URL 参数中)
- 错误信息、日志中泄露 Session ID
- Referer 头泄露
防御措施:
Cookie 安全属性
- HttpOnly:禁止 JavaScript 读取 Cookie,防止 XSS 窃取
- Secure:仅在 HTTPS 连接中发送 Cookie,防止网络窃听
- SameSite:限制跨站请求携带 Cookie,防 CSRF
Strict:完全禁止跨站Lax:允许部分跨站(GET 请求 + 顶级导航)None:允许跨站,需配合 Secure
Session ID 安全
- 使用足够随机、足够长的 Session ID(至少 128 位熵)
- 禁止在 URL 中传递 Session ID
- 登录后重新生成 Session ID(防 Session 固定)
Session 生命周期管理
- 设置合理的过期时间(空闲超时 + 绝对超时)
- 用户登出时彻底销毁 Session(服务端 + 客户端)
- 修改密码后使旧 Session 失效
- 定期轮换 Session ID
其他防护
- 绑定用户特征(IP、User-Agent),异常时要求重新验证
- 敏感操作二次验证
- 异地登录提醒
追问延伸:
- Session 和 Cookie 有什么区别和联系?
- 设置了 HttpOnly 的 Cookie 还能被 CSRF 利用吗?
- SameSite=None 必须配合 Secure 属性吗?为什么?
- 如果用户禁用了 Cookie,Session 还能用吗?
- 分布式 Session 有哪些实现方式?各有什么安全问题?
Q7: API接口安全如何设计? 「🔴 高级」
考察点:考察 API 安全体系的全局设计能力。筛掉只关注功能开发、缺乏安全体系思维的后端开发。
参考答案:
API 接口安全设计需要从多个维度构建纵深防御体系,确保接口的机密性、完整性和可用性。
安全设计八大维度:
认证(Authentication)
- 确认"你是谁"
- 方案:
- API Key / Secret(适用于服务间调用)
- Token 认证(JWT、OAuth 2.0)
- mTLS(双向证书认证,高安全场景)
- HMAC 签名
授权(Authorization)
- 确认"你能做什么"
- 方案:
- RBAC 角色权限控制
- ABAC 属性权限控制
- 接口级别的权限校验
- 数据级别的权限隔离
限流(Rate Limiting)
- 防止暴力破解、爬虫、DDoS
- 方案:
- 令牌桶/漏桶算法
- 按用户/IP/接口维度限流
- 分级限流(全局限流 → 业务限流 → 接口限流)
签名(Signature)
- 防止数据被篡改,防重放
- 方案:
- 对请求参数 + 时间戳 + 随机数 进行签名
- 使用 HMAC-SHA256 算法
- 服务端验证签名有效性
防重放攻击(Replay Protection)
- 防止请求被截获后重复发送
- 方案:
- Timestamp + 时间窗口(如 5 分钟内有效)
- Nonce 随机数(服务端记录已使用的 nonce)
- 序号机制(请求序号递增)
数据加密
- 传输加密:全站 HTTPS,TLS 1.2+
- 敏感字段加密:身份证、手机号、银行卡等字段在存储时加密
- 响应脱敏:返回数据时对敏感信息打码
输入校验
- 防止注入类攻击
- 方案:
- 参数格式校验(白名单)
- SQL 注入防护(预编译)
- XSS 防护(输出编码)
- 上传文件校验
审计日志
- 记录所有关键操作,用于溯源和合规
- 记录内容:谁(用户ID)、什么时候(时间戳)、做了什么(接口+参数)、结果(成功/失败)、IP、设备信息
- 日志保护:防篡改、定期备份、独立存储
额外的安全措施:
- 接口版本管理:老版本接口及时下线
- 错误信息处理:不暴露系统内部错误详情
- CORS 配置:严格的跨域策略
- WAF 防护:接入 Web 应用防火墙
- 安全测试:定期渗透测试、漏洞扫描
追问延伸:
- API 签名的设计思路是什么?如何防止签名被绕过?
- 什么是重放攻击?Timestamp + Nonce 的方案有什么问题?
- 微服务架构下 API 安全如何设计?网关层做什么?服务层做什么?
- 如何设计一个安全的开放平台 API 体系?
- GraphQL API 和 REST API 在安全上有什么不同的关注点?