安全与认证面试题精选
Java 后端真实面试专题 · 安全与认证篇
真实面经里只要项目是 SaaS / 政企 / 中后台,必问 JWT、单点登录、多租户、权限、SQL 注入。每题三段: ① 标准答(讲透)→ ② 拓展(成体系带出关联点和必追问的)→ ③ 怎么接到你自己的项目。
年限标签:
🟢 3年内🔴 3年+
1. 🟢 JWT 是什么?结构和原理?
标准答:JWT(JSON Web Token)是一种无状态的令牌,由三段用点号连接:Header(算法)、Payload(用户信息、过期时间等声明)、Signature(用密钥对前两段签名)。服务端登录时签发 JWT 给客户端,客户端每次请求带上,服务端验签就知道身份,不用在服务端存会话。
拓展:
- "JWT 安全吗?Payload 能放密码吗?"——Payload 只是 Base64 编码、不是加密,任何人能解开看到,所以不能放敏感信息;安全靠签名防篡改(改了验签就失败)。
- "JWT 能注销吗?"——无状态导致主动失效难,常用方案:短过期 + refresh token、或用 Redis 黑名单。
- 对称签名(HS256)vs 非对称(RS256)。
往项目引 ⭐:"我项目用 JWT 做认证——登录签发 token、网关验签后把用户信息透传给各服务,服务端不存 session、天然适合分布式。敏感信息不放 Payload,注销靠 Redis 黑名单 + 短过期。"
2. 🟢 JWT 和 Session 的区别?分布式下为什么用 JWT?
标准答:
- Session:状态存在服务端,靠 cookie 里的 sessionId 关联。分布式下多台服务器 session 不共享,要 session 复制或集中存(Redis)。
- JWT:状态(用户信息)在 token 里、服务端不存,天然无状态,任何一台服务器验签就能识别身份,适合分布式/微服务。
拓展:
- JWT 缺点:不能方便地主动失效、token 变大、刷新麻烦。
- Session + Redis 集中存储也是分布式可行方案,看取舍。
- 移动端、前后端分离更适合 JWT。
往项目引 ⭐:"我项目是微服务 + 前后端分离,用 JWT 而不是 Session——无状态、任何服务实例都能验签识别用户,不用做 session 共享。只是注销和续期要额外设计(refresh token + 黑名单)。"
3. 🔴 单点登录(SSO)的原理?
标准答:一处登录、多个系统互通免再登。核心是共享认证中心:用户在认证中心登录拿到凭证(token/票据),访问各子系统时带上凭证、子系统去认证中心校验。CAS 流程是"重定向到认证中心登录 → 拿 ticket → 子系统用 ticket 换用户信息"。
拓展:
- "JWT 怎么做 SSO?"——各系统共享密钥/公钥验签同一个 JWT 即可免登。
- 跨域 SSO 的难点是 cookie 不能跨域,常用 token 放统一认证域或 URL 传递。
- 还有基于 OAuth2 的 SSO。
往项目引 ⭐:"我项目几个子系统用 SSO——统一认证中心签发 JWT,各子系统共享验签逻辑,用户登录一次、访问各系统免再登。理解'共享认证中心 + 凭证校验'这个核心就能讲清各种 SSO 方案。"
4. 🔴 Spring Security 的工作流程?
标准答:核心是过滤器链(FilterChain)。请求进来依次过一串过滤器:
- 认证过滤器(如 UsernamePasswordAuthenticationFilter / 自定义 JwtAuthenticationFilter)拦截登录或解析 token。
- 调 AuthenticationManager → UserDetailsService 加载用户、校验。
- 认证成功,把 Authentication 存入 SecurityContextHolder(ThreadLocal)。
- 后续授权过滤器做权限校验(
@PreAuthorize、URL 匹配)。 - 未认证返回 401、无权限返回 403。
拓展:
- "JWT 怎么和 Security 集成?"——自定义一个过滤器解析 token、构建 Authentication 放进 SecurityContext,实现无状态认证。
- 认证(你是谁)vs 授权(你能干什么)要分清。
往项目引 ⭐:"我项目用 Spring Security + JWT——自定义 JwtAuthenticationFilter 解析 token、填充 SecurityContext,再用 @PreAuthorize 做方法级权限。能把'过滤器链 → 认证 → 授权'这条线讲清就够了。"
5. 🔴 OAuth2 是什么?有哪几种授权模式?
标准答:OAuth2 是授权框架,让第三方在不拿到密码的情况下、被授权访问用户资源(如"用微信登录某网站")。四种模式:
- 授权码模式(最安全最常用,如第三方登录)。
- 简化/隐式模式(前端应用,已不推荐)。
- 密码模式(自家应用,直接用账密换 token)。
- 客户端模式(服务间,没有用户)。
拓展:
- 授权码模式:用户授权 → 拿 code → 后端用 code + secret 换 token,code 一次性、token 不暴露给前端。
- OAuth2 解决"授权",OIDC(OpenID Connect)在它上面加了"认证"(身份)。
往项目引 ⭐:"我项目对接第三方登录(微信/钉钉)用授权码模式——前端拿 code、后端换 token 和用户信息。内部服务间调用用客户端模式。能区分'哪种场景用哪种模式'是关键。"
6. 🟢 双 token(access token + refresh token)怎么设计?
标准答:
- access token:短期有效(如 30 分钟),每次请求带它,泄露了危害也小。
- refresh token:长期有效(如 7 天),只用来在 access token 过期时换新的 access token,不参与日常请求。 access 过期 → 用 refresh 换新 access → refresh 也过期才要重新登录。
拓展:
- "为什么要双 token?"——平衡安全和体验:access 短期降低泄露风险、refresh 长期避免频繁登录。
- refresh token 要安全存储、可吊销(存 Redis,注销时删)。
- 前端要处理"access 过期自动用 refresh 续期并重试请求"(拦截器 + 请求队列)。
往项目引 ⭐:"我项目用双 token——access 30 分钟、refresh 7 天,前端 Axios 拦截器在收到 401 时自动用 refresh 换新 token 并重试原请求,用户无感知。refresh 存 Redis,注销时删掉实现吊销。"
7. 🔴 多租户 SaaS 的数据怎么隔离?租户 id 怎么透传?
标准答:三种隔离——独立库(物理隔离)、独立 Schema、共享表 + tenant_id(成本最低、最常用)。共享表方案的关键:
- 请求进来从 token 解析出租户 id,存 ThreadLocal。
- 用 MyBatis 拦截器自动给所有 SQL 拼上
where tenant_id = ?,业务代码无感知。
拓展:
- "连表查询怎么拼租户条件?"——拦截器要解析 SQL、给每张涉及的租户表都加条件(用 SQL 解析库如 JSqlParser)。
- "怎么防止串数据?"——所有租户表必须带 tenant_id、拦截器强制加条件、关键查询加测试覆盖。
- 跨租户的统计走单独的、显式带租户维度的查询。
往项目引 ⭐:"我项目是 SaaS,用 MyBatis 拦截器 + JSqlParser 自动给 SQL 拼租户条件,租户 id 从 token 解析存 ThreadLocal,业务层完全无感知——从根上防越权查到别家数据。连表时拦截器给每张租户表都加条件。"
8. 🔴 请求头里的租户 id 被篡改了怎么办?
标准答:绝不能信任客户端传的租户 id。正确做法是租户 id 从服务端校验过的凭证里取——把租户 id 编码进 JWT 的 Payload,JWT 有签名防篡改,改了验签就失败。服务端解析 JWT 拿租户 id,而不是读请求头的明文。
拓展:
- 这是"永远不信任客户端输入"的安全原则。
- 同理,用户 id、权限也都从校验过的 token 里取,不读前端传的。
往项目引 ⭐:"我项目租户 id 编进 JWT、靠签名防篡改,服务端从解析后的 token 取租户 id,不读请求头明文——所以不存在'改请求头串租户'的问题。这题考的就是'不信任客户端输入'的安全意识。"
9. 🟢 怎么用 AOP 做统一鉴权 / 自动鉴权注解?
标准答:自定义注解(如 @RequiresPermission("order:create"))打在方法上,用 AOP 切面在方法执行前拦截:从上下文取当前用户的权限、和注解要求的权限比对,没权限就抛异常拦掉。
拓展:
- 也可以用 Spring Security 的
@PreAuthorize,原理类似(基于 AOP)。 - 注解 + AOP 的好处是声明式、不侵入业务、统一管理。
- 要注意 AOP 自调用失效问题。
往项目引 ⭐:"我项目用自定义 @RequiresPermission 注解 + AOP 做接口鉴权——切面里取当前用户权限和注解比对,无权限直接拦。业务方法上加个注解就行、不用每个方法写鉴权代码。"
10. 🔴 SQL 注入是什么?怎么判断和防范?
标准答:SQL 注入是把恶意 SQL 片段拼进输入参数、改变原 SQL 语义(如 ' or '1'='1)窃取或破坏数据。防范:
- 用预编译(PreparedStatement / MyBatis 的
#{}),参数作为值传入、不参与 SQL 解析——这是根本手段。 - 避免用
${}拼接;不得不用(动态表名/排序)就做白名单校验。 - 输入校验、最小权限数据库账号。
拓展:
- "怎么判断有没有注入点?"——对参数构造特殊字符(引号、or、注释
--)看 SQL 是否异常,安全扫描工具(如 sqlmap)会做这事。 - 注入只是 OWASP Top10 之一,还有 XSS、CSRF 等。
往项目引 ⭐:"我项目查询全用 MyBatis #{} 预编译防注入;只有动态排序字段必须用 ${},我做了字段白名单校验。理解'预编译让参数不参与 SQL 解析'才知道为什么 #{} 能防注入。"
11. 🟢 XSS 和 CSRF 是什么?怎么防?
标准答:
- XSS(跨站脚本):攻击者注入恶意脚本到页面,别的用户访问时执行(盗 cookie 等)。防:对用户输入/输出做转义、设置 CSP、HttpOnly cookie。
- CSRF(跨站请求伪造):诱导已登录用户在不知情下发出请求。防:CSRF token、校验 Referer、SameSite cookie。
拓展:
- XSS 是"注入脚本",CSRF 是"冒用身份发请求"。
- 前后端分离 + JWT(不依赖 cookie)能减轻 CSRF。
往项目引 ⭐:"我项目对富文本输入做转义防 XSS、cookie 设 HttpOnly;因为用 JWT 放在 header 而非 cookie,CSRF 风险也低。能区分这两个常考的 Web 安全点就够。"
12. 🟢 用户密码应该怎么存储?
标准答:绝不能明文存,也不能简单 MD5(能被彩虹表破解)。正确做法:加盐(salt)+ 慢哈希,用 BCrypt / PBKDF2 / Argon2——每个用户随机盐、哈希慢(抗暴力破解),验证时对比哈希。
拓展:
- "为什么加盐?"——防止相同密码哈希值相同、防彩虹表。
- BCrypt 自带盐、可调计算强度,是常用选择。
- 传输层还要 HTTPS 防中间人。
往项目引 ⭐:"我项目用 Spring Security 的 BCryptPasswordEncoder 存密码——自带随机盐、慢哈希,数据库泄露了也很难反推原密码。绝不会明文或裸 MD5。"
13. 🔴 RBAC 权限模型怎么设计?
标准答:RBAC(基于角色的访问控制)核心五张表——用户、角色、权限(菜单/按钮/接口)、用户-角色、角色-权限。用户绑角色、角色绑权限,鉴权时查用户 → 角色 → 权限集合,判断有没有要求的权限。
拓展:
- 好处:权限和用户解耦,改角色权限就影响一批人,便于管理。
- 进阶:数据权限(能看哪些数据,如只看本部门)、字段权限。
- 还有 ABAC(基于属性)等更细的模型。
往项目引 ⭐:"我项目权限用标准 RBAC 五张表——用户绑角色、角色绑菜单和接口权限,前端按权限渲染菜单、后端用注解 + AOP 校验接口权限。还做了数据权限(按部门过滤数据)。"
14. 🟢 服务之间调用怎么做鉴权?
标准答:内部服务调用也要鉴权,避免被绕过。常见:
- 网关统一鉴权:外部请求在网关校验 token,内部服务信任网关透传的用户信息。
- 服务间用内部 token / OAuth2 客户端模式:服务自己的身份凭证。
- 内网隔离 + 白名单。
拓展:
- "Feign 调用怎么传递用户信息?"——用拦截器把当前用户 token/信息加到请求头透传下去。
- 不能假设"内网就安全",零信任趋势下内部也要鉴权。
往项目引 ⭐:"我项目外部请求在网关统一验 JWT,内部服务间用 Feign 拦截器透传用户上下文,关键服务再校验。这样既不重复登录、又不会因为信任内网而被绕过。"
15. 🟢 接口怎么防刷、防重放攻击?
标准答:
- 防刷:限流(按 IP/用户/手机号)、验证码、滑动验证。
- 防重放:请求带时间戳 + 一次性 nonce + 签名,服务端校验签名、时间窗口、nonce 是否用过(Redis 记录),重复请求被拦。
拓展:
- 重放攻击是把抓到的合法请求再发一遍,nonce + 时间戳能防。
- 关键接口(支付、下单)尤其要防。
往项目引 ⭐:"我项目敏感接口加了签名 + 时间戳 + nonce 防重放——nonce 存 Redis 设过期,用过的直接拦;登录、短信接口再加限流和验证码防刷。"
16. 🟢 HTTPS 的原理?为什么安全?
标准答:HTTPS = HTTP + TLS。通过非对称加密协商出一个对称密钥,之后用对称密钥加密通信。握手时服务端用CA 证书证明身份(防中间人),客户端验证证书后协商密钥。既加密(防窃听)又验证身份(防冒充)。
拓展:
- "为什么不全程非对称?"——非对称慢,只用来安全地交换对称密钥,后续用对称加密(快)。
- 证书链、CA 信任是防中间人的关键。
往项目引 ⭐:"我项目对外接口全走 HTTPS,敏感数据传输加密、靠证书防中间人。理解'非对称协商密钥 + 对称加密通信'就能讲清 HTTPS 为什么既安全又不慢。"
17. 🔴 什么是越权?水平越权和垂直越权?
标准答:
- 水平越权:A 用户访问到了 B 用户的数据(同级别,如改 URL 里的 id 看别人订单)。
- 垂直越权:低权限用户访问了高权限功能(如普通用户调管理员接口)。 防范:每次操作都校验"当前用户是否有权访问这条数据/这个功能",不只看登录态。
拓展:
- 水平越权要做数据归属校验(这条订单是不是你的)。
- 垂直越权要做功能权限校验(RBAC)。
- 多租户串数据本质也是水平越权。
往项目引 ⭐:"我项目查订单详情时除了校验登录,还校验'这个订单是不是当前用户/租户的',防水平越权;接口用 RBAC 注解防垂直越权。越权是很实际的安全漏洞,能说出两种区别和防法很加分。"
18. 🟢 敏感数据(手机号、身份证)怎么保护?
标准答:
- 存储加密:敏感字段加密存(如 AES),或脱敏存。
- 展示脱敏:返回前端时打码(
138****5678)。 - 传输加密:HTTPS。
- 权限控制 + 审计:谁能看、看了记日志。
拓展:
- 加密要管好密钥(KMS)。
- 可搜索的加密字段要存一个哈希索引列来支持等值查询。
往项目引 ⭐:"我项目用户手机号、身份证加密存储、列表展示脱敏打码、查询用哈希列匹配,敏感操作记审计日志——符合等保和隐私合规要求。"
19. 🟢 你项目的登录认证整体是怎么做的?
标准答:串起来讲——登录校验账密(BCrypt)→ 签发双 token(access + refresh)→ 客户端带 access 请求 → 网关验签、解析用户和租户 id 透传 → 服务端从上下文取身份 → RBAC 鉴权 → access 过期用 refresh 续期 → 注销删 Redis 里的 token。
拓展:
- 这是一道"串场题",把前面的点连成完整链路。
- 能讲清"认证 + 授权 + 多租户 + 续期 + 注销"整条线就很完整。
往项目引 ⭐:"我项目认证链路是:BCrypt 校验密码 → 签 JWT 双 token(含用户和租户 id)→ 网关验签透传 → RBAC 鉴权 → refresh 续期 → 注销删 Redis。一条线把登录、鉴权、多租户、续期、注销都覆盖了,面试官一听就知道你做过完整的。"
20. 🟢 怎么防止接口被重复提交(结合安全)?
标准答:和幂等一类——前端置灰 + 后端 token 机制(进页面发一次性 token、提交校验并删除)+ 唯一索引/状态机兜底。用 Redis 存 token、Lua 原子校验删除。
拓展:
- 防重复提交是用户体验 + 数据一致问题,也和防重放相关。
- 关键是"服务端判定唯一一次",不能只靠前端。
往项目引 ⭐:"我项目下单防重复提交用 Redis token + Lua 原子校验删除,加订单号唯一索引兜底,前端再置灰按钮——三重保险,重复点击只成功一笔。"
你能答到第几层?
- 三段都能答、还能往项目引:安全认证这块你稳了,SaaS/政企岗尤其吃这个。
- 标准答 + 拓展能成体系答:知识够,差把它接到项目的认证链路上。
- 标准答都磕巴:安全有主线(认证 JWT/SSO → 授权 RBAC → 多租户 → 常见漏洞防范),跟着学一遍 + 一个有登录鉴权的项目就懂。
这是面试专题的「安全与认证篇」,网站上还有并发、MySQL、Redis、Spring、微服务、消息队列、JVM、项目场景等系统整理。 🌐 更多真实面试专题与资料:smallredtech.com 💬 想系统学 / 简历与辅导咨询,加微信:Ahongbb666(备注「面试题」)