跳到正文
Java 入门到面试指南
返回

06-认证与安全

阶段:框架篇 | 用法:todo-list 项目做到「能登录、能鉴权」时学这一篇;面试安全题(JWT/CSRF/密码存储)基本都在这里。先读完再动项目,安全方案别自己发明。

学习目标

  • 能画出一个「账号密码登录 → 发 Token → 后续请求带 Token → 网关/拦截器校验」的完整时序。
  • 说清 Cookie/Session/JWT 三者的取舍,以及分布式下 Session 共享的三种方案。
  • 记住密码存储铁律:加盐慢哈希(BCrypt),以及为什么「忘记密码只能重置不能找回」。
  • 能解释 XSS / CSRF / SQL 注入 三种攻击的原理与防御各一条,且不混淆。
  • 理解 RBAC 权限模型,能设计「用户-角色-权限-资源」四张表。

核心知识点

1. 认证 vs 鉴权(先分清这两个词)

  • 认证 Authentication:你是谁——校验凭据(密码/短信/扫码/OAuth)。
  • 鉴权 Authorization:你能干什么——校验权限(这个角色能不能删这条订单)。
  • 一句话:认证是门卫查证件,鉴权是前台刷卡开闸。Spring Security 的两大组件一一对应(AuthenticationManager / AccessDecisionManager 或新版 AuthorizationManager)。

2. 会话方案演进:Cookie+Session → Token → JWT ⭐

方案状态存哪扩容跨域注销
Session(Cookie 传 JSESSIONID)服务端内存要共享(见下)同域才行服务端删,立即生效
集中式 Session(Redis)Redis天然共享同上立即生效
JWT Token(放 Authorization: Bearer)不存(自包含)无状态最省事无限制难,需黑名单/短过期
  • JWT 结构:header.payload.signature,Base64URL 编码——是签名不是加密,payload 里别放敏感信息,任何人都能 base64 解开看。
  • HS256(对称,单服务自用)vs RS256(非对称,签发方私钥签、验证方公钥验,微服务/开放平台用)。
  • 过期与刷新:Access Token 短期(15min2h)+ Refresh Token 长期(730 天,存库可吊销)。口径:JWT 的无状态是用「吊销难」换来的。
  • 常见坑:alg: none 绕过验签(库要关支持)、密钥泄露等于系统沦陷、把 JWT 当加密信封。
  • 分布式 Session 三方案:粘滞会话(同一 IP 固定路由到同一台,扩容即乱)、Session 复制(集群广播,小集群才用)、集中存储(Spring Session + Redis,事实标准)。

3. 密码与敏感数据 ⭐

  • 铁律:服务端永远不存明文密码,也不存可逆密文。忘记密码只能重置不能告诉你原密码——因为存的是哈希,本来就无法还原(这正是安全的证明)。
  • 正确姿势:BCrypt(或 Argon2/PBKDF2),自带随机盐、慢哈希抗暴力。encoder.encode(raw) 一次一盐,比对用 encoder.matches(raw, encoded)。
  • 三个概念别混:
    • 哈希 Hash:单向,不可逆 → 存密码用它(MD5/SHA1 太快来不及加盐,禁用)。
    • 加密 Encryption:双向有密钥 → AES 存要还原的数据(手机号、API key),RSA 公加密私解密。
    • 编码 Encoding:无损格式转换(Base64/URL-encode)→ 不是安全手段,Base64 不是加密是常识题。
  • 加盐(Salt)作用:同密码不同哈希,破彩虹表攻击;慢哈希作用:把 GPU 爆破成本拉高 1000 倍。
  • 脱敏:日志和返回里的手机号 138****1234、身份证、银行卡——序列化时处理(Jackson 注解或 MyBatis TypeHandler),别在业务代码里手搓 substring。

4. 三种经典攻击与防御 ⭐

攻击原理一句话发生地防御
SQL 注入用户输入拼进 SQL 改变了语义(' or 1=1 --)数据库层预编译 #{}(MyBatis)、最小权限 DB 账号、WAF 兜底
XSS 跨站脚本恶意 JS 注入页面,偷 Cookie/冒充操作浏览器输出转义、HttpOnly Cookie、CSP、前端框架默认转义
CSRF 跨站请求伪造借用户在目标站的已登录 Cookie,诱导浏览器发伪造请求浏览器SameSite Cookie、CSRF Token、校验 Origin/Referer
  • 记忆锚点:SQL 注入是「数据被当代码执行」,XSS 是「数据在浏览器被当代码执行」,CSRF 是「请求冒充了合法用户」。
  • CSRF 只对「自动携带凭据(Cookie)」的方案有效,Header+JWT 方案天然免疫大半(浏览器不会自动带 Authorization 头)——这是面试加分点。
  • SQL 注入防御呼应《MyBatis》的 #{} vs ${}:${} 就是字符串拼接,order by 场景不得不用 ${} 时要做白名单校验。

5. RBAC 权限模型

  • 模型:用户 → 角色 → 权限 → 资源,用户不直接挂权限,一律通过角色中转(换岗位只改角色不改人)。
  • 四张核心表:user、role、permission、user_role、role_permission(多对多两张中间表)。
  • 落地分层:前端按钮显隐(体验层,不是安全)+ 后端接口鉴权(安全层,缺一不可)。接口上用注解(Spring Security @PreAuthorize("hasRole('ADMIN')") 或自研拦截器)。
  • 面试一句话:「前端控制是体验,后端控制才是安全」。

6. 第三方登录(OAuth2 速览)

  • 场景:微信/GitHub 授权登录。角色:资源所有者(用户)、客户端(你的应用)、授权服务器(微信)、资源服务器(微信 API)。
  • 授权码模式(最常用)时序:跳授权页 → 用户同意 → 回调带 code → 你的后端用 code+client_secret 换 access_token → 拿用户信息。
  • 关键点:code 走前端、token 换在后端(client_secret 绝不能放前端);state 参数防 CSRF。
  • 了解即可,别展开实现——面试问到说出时序就够。

动手实践

任务 1:给 todo-list 加登录发 JWT

  • 要求:POST /login(用户名+密码,BCrypt matches 校验)→ 签发 JWT(含 userId、role,过期 2h);写一个拦截器:Authorization: Bearer 验签+验过期,失败统一返回 401;除 /login 外全部接口拦截。
  • 验收标准:不带 token 访问受保护接口返回 401;带篡改过的 token 返回 401;把过期时间调成 30 秒,等待后访问能复现 401;能说出为什么 payload 里不放手机号。

任务 2:亲手玩一次 SQL 注入与防御

  • 要求:先用 ${} 拼接写一个查询接口,用 ' OR '1'='1 复现全表泄露;再改 #{} 验证免疫;对「按列名动态排序」参数做白名单(只允许 id|create_time|priority)。
  • 验收标准:能演示注入前后差异;白名单外的列名传入直接 400;说出预编译防御的原理(SQL 结构与参数分离,参数永远是数据)。

任务 3:RBAC 四表 + 一个接口级鉴权

  • 要求:建五张表(user/role/permission+两张中间表);登录时把角色写进 JWT payload;DELETE /todos/{id} 只允许 ADMIN 角色;普通用户删除自己的记录放行(数据级权限,与功能级权限的区别)。
  • 验收标准:ADMIN 删除任意记录 200,USER 删别人的 403、删自己的 200;能说出「功能级权限」与「数据级权限」分别拦在哪一层。

高频面试题

  • Q:JWT 的组成部分与校验流程? —— header.payload.signature 三段 Base64URL,服务端用密钥重算签名比对,再查 exp;是签名不是加密 | 详见《03-IO模型与网络编程》
  • Q:为什么 JWT 注销难,怎么解决? —— 无状态服务端不存,只能等过期;缓解:短期 Access + 可吊销 Refresh、Redis 黑名单、改密码全局失效 | 详见《06-认证与安全》
  • Q:XSS 和 CSRF 的区别与各自防御? —— XSS 是注入脚本偷凭据(转义+HttpOnly+CSP),CSRF 是借凭伪造请求(SameSite+Token+验 Origin) | 详见《06-认证与安全》
  • Q:密码怎么存才安全? —— BCrypt/Argon2 加盐慢哈希,禁止 MD5/SHA 裸哈希与可逆加密;matches 比对 | 详见《06-认证与安全》
  • Q:分布式系统下 Session 怎么共享? —— 粘滞会话/集群复制/Spring Session 存 Redis(事实标准),或直接改无状态 Token | 详见《03-IO模型与网络编程》
  • Q:预编译为什么能防 SQL 注入? —— 先编译 SQL 结构再填参数,参数被当纯数据绑定,改变不了语法结构 | 详见《MyBatis》
  • Q:RBAC 是什么,为什么用户不直接挂权限? —— 用户-角色-权限三层,角色是批量授权的中转站,人员/权限变动只动一层 | 详见《06-认证与安全》
  • Q:OAuth2 授权码模式为什么要后端换 token? —— code 经浏览器可被截但短命且需 client_secret 才能换 token,secret 不落前端 | 详见《06-认证与安全》

推荐资料

资料用来干什么链接
JavaGuide 认证授权专题(JWT/SSO 详解)JWT 与单点登录的完整推导https://javaguide.cn/system-design/security/
JavaGuide 常见加密算法总结哈希/对称/非对称选型对照https://javaguide.cn/system-design/security/encryption-algorithms.html
pdai.tech 系统设计与安全RBAC/权限体系的结构图视角https://pdai.tech/md/arch/arch-z-design.html
廖雪峰 Web 前端安全篇(跨站脚本/CSRF)攻击原理的通俗讲解https://www.liaoxuefeng.com/book/0001373845519712840765955243109f0516b23e69718a6000
码工具 Java API(MessageDigest/SecretKey 相关)动手实现时查签名https://www.matools.com/api/java8