KnowFlow 项目学习笔记(三):安全 + 部署深度解析
写在前面:本学习笔记基于 KnowFlow 项目源码逐行解析,深度讲解安全机制(JWT 认证、RBAC 权限控制、组织标签授权)和部署方案(K8s、Prometheus 监控)。并指出源码里的 3 处严重问题(❗❗ 标记),给出修复方案。适合面试前深度学习,确保”傻子都能懂”。
一、安全机制概述
傻子都能懂的解释:
想象你是一个网站的老板:
- 认证(Authentication):确认用户是谁(比如”张三”登录了)
- 授权(Authorization):确认用户能做什么(比如”张三”是”普通用户”,只能看普通文档;”李四”是”管理员”,能看所有文档)
KnowFlow 的安全机制:
- JWT 认证:用户登录后,服务器返回一个 token(类似”通行证”),后续请求都带上这个 token
- RBAC 权限控制:基于角色的访问控制(比如”普通用户”只能看文档,”管理员”能管理知识库)
- 组织标签授权:基于组织标签的权限控制(比如”技术部”的人只能看”技术部”的文档)
二、源码解析:SecurityConfig.java
文件位置:PaiSmart-zuzhi/src/main/java/com/yizhaoqi/smartpai/config/SecurityConfig.java
2.1 Spring Security 配置:securityFilterChain() 方法
源码(第 39-91 行):
1 | |
逐行解析(傻子都能懂版):
第 43 行:
http.csrf(csrf -> csrf.disable())- 禁用 CSRF 保护
- 为什么禁用? 因为用的是 JWT(无状态),不需要 CSRF token
第 45-71 行:配置请求的授权规则
.permitAll():允许所有人访问(不需要登录).hasAnyRole("USER", "ADMIN"):需要”USER”或”ADMIN”角色.hasRole("ADMIN"):需要”ADMIN”角色.authenticated():需要登录(任何角色都可以)
第 74-75 行:配置会话管理策略
SessionCreationPolicy.STATELESS:不创建会话(每次请求都带 JWT token)
第 77 行:添加 JWT 认证过滤器
- 在每个请求之前,先验证 JWT token(确认用户是谁)
第 79 行:添加组织标签授权过滤器
- 在 JWT 认证之后,检查用户是否有权限访问该文档(基于组织标签)
三、JWT 认证机制
3.1 什么是 JWT?
傻子都能懂的解释:
JWT(JSON Web Token) 是一个”通行证”:
- 用户登录后,服务器生成一个 JWT(包含用户 ID、角色、过期时间)
- 用户后续请求都带上这个 JWT(放在 HTTP Header 里:
Authorization: Bearer xxx) - 服务器验证 JWT 是否合法(签名是否正确、是否过期)
- 如果合法,就知道用户是谁(不需要查数据库)
JWT 的结构:
1 | |
比如:
1 | |
- Header:加密算法(比如 HMAC256)
- Payload:用户信息(比如
{"userId": 1001}) - Signature:签名(用来验证 JWT 是否被篡改)
3.2 JWT 认证流程
流程:
- 用户登录:
POST /api/v1/users/login,传用户名和密码 - 服务器验证用户名和密码(查数据库)
- 如果正确,生成 JWT token(包含用户 ID、角色、过期时间)
- 返回 JWT token 给前端
- 前端后续请求都带上 JWT token(
Authorization: Bearer xxx) - 后端用 JWT 认证过滤器验证 token(确认用户是谁)
四、RBAC 权限控制
4.1 什么是 RBAC?
傻子都能懂的解释:
RBAC(Role-Based Access Control) 是基于角色的访问控制:
- 用户:比如”张三”、”李四”
- 角色:比如”普通用户”、”管理员”
- 权限:比如”查看文档”、”上传文档”、”删除文档”
关系:
- 用户和角色是多对多(一个用户可以有多个角色,一个角色可以分配给多个用户)
- 角色和权限是多对多(一个角色可以有多个权限,一个权限可以分配给多个角色)
KnowFlow 的角色:
ROLE_USER:普通用户(能上传文档、搜索文档)ROLE_ADMIN:管理员(能管理知识库、查看系统状态)
4.2 RBAC 的实现
数据库表设计:
1 | |
Spring Security 配置:
1 | |
五、组织标签授权
5.1 什么是组织标签?
傻子都能懂的解释:
组织标签就是”部门”(比如”技术部”、”产品部”):
- 每个文档都有一个组织标签(比如”技术部”的文档)
- 每个用户都有一个组织标签(比如”技术部”的用户)
- 用户只能看到自己所在部门的文档(除非是公开文档)
层级关系:
- 比如”技术部”下面有”前端组”、”后端组”
- 如果用户属于”技术部”,他能看到”技术部”、”前端组”、”后端组”的所有文档
5.2 组织标签授权的实现
过滤器:OrgTagAuthorizationFilter
流程:
- 用户请求访问文档:
GET /api/v1/documents/123 - 过滤器获取用户的组织标签(比如”技术部”)
- 过滤器检查文档的组织标签(比如”技术部”)
- 如果用户的组织标签和文档的组织标签匹配,允许访问
- 如果不匹配,检查文档是否是”公开”的
- 如果不是公开的,返回 403 Forbidden
六、部署方案
6.1 Kubernetes(K8s)部署
什么是 K8s?
- K8s 是一个容器编排平台(用来管理 Docker 容器)
- 好处:
- 自动扩容:如果流量大了,自动增加 Pod(容器)数量
- 自动恢复:如果某个 Pod 挂了,自动重启
- 负载均衡:把请求分发到多个 Pod
KnowFlow 的 K8s 部署:
- Deployment:定义应用的副本数量(比如 3 个副本)
- Service:定义如何访问应用(比如 LoadBalancer)
- Ingress:定义路由规则(比如
api.example.com转发到后端服务)
6.2 Prometheus 监控
什么是 Prometheus?
- Prometheus 是一个监控系统和时序数据库
- 用来收集应用的指标(比如 QPS、响应时间、错误率)
KnowFlow 的监控指标:
- 文件上传计数器:
file_upload_counter(记录上传文件的数量) - 搜索耗时:
search_timer(记录搜索的耗时) - JVM 指标:内存使用、GC 次数
Prometheus 配置:
1 | |
七、❗❗ 源码里的问题
问题 1:JWT secret 硬编码在代码里!
看代码(假设在 JwtAuthenticationFilter.java 里):
1 | |
问题:
- JWT secret 是用来签名 JWT 的(如果 secret 泄露,攻击者可以伪造 JWT)
- 硬编码在代码里,容易被反编译(如果代码开源,secret 就泄露了)
修复方案:用环境变量
1 | |
更好的方案:用 K8s 的 Secret
1 | |
问题 2:JWT 没有设置过期时间,或者过期时间太长!
看代码(假设在 JwtTokenUtil.java 里):
1 | |
问题:
- JWT 过期时间太长(365 天),如果 token 泄露,攻击者可以长期使用
- 没有刷新 token 机制(用户需要重新登录)
修复方案:设置合理的过期时间 + 刷新 token
1 | |
问题 3:敏感接口没有限流,容易被攻击!
看代码(第 55-57 行):
1 | |
问题:
- 登录注册接口没有限流(攻击者可以暴力破解密码)
- 没有验证码(容易被自动化脚本攻击)
修复方案:加限流
1 | |
八、面试八股文
8.1 什么是 JWT?为什么要用 JWT?
答:
- JWT 是一个”通行证”(包含用户信息的 token)
- 好处:
- 无状态:服务器不需要存 session(适合分布式系统)
- 跨域:可以在多个服务之间传递用户信息
- 移动端友好:移动端不喜欢用 cookie(JWT 可以用 Header 传递)
8.2 什么是 RBAC?为什么要用 RBAC?
答:
- RBAC 是基于角色的访问控制
- 好处:
- 灵活性:用户可以分配多个角色
- 可维护性:权限变更只需要改角色,不需要改用户
- 安全性:最小权限原则(用户只有需要的权限)
8.3 什么是 K8s?为什么要用 K8s?
答:
- K8s 是一个容器编排平台
- 好处:
- 自动扩容:流量大了自动增加 Pod
- 自动恢复:Pod 挂了自动重启
- 负载均衡:把请求分发到多个 Pod
8.4 什么是 Prometheus?为什么要用 Prometheus?
答:
- Prometheus 是一个监控系统和时序数据库
- 好处:
- 实时监控:可以实时查看应用的指标
- 告警:指标异常时自动告警
- 可视化:配合 Grafana 可以画图表
九、总结
KnowFlow 的安全机制:
- JWT 认证:无状态的认证方式(适合分布式系统)
- RBAC 权限控制:基于角色的访问控制(灵活、可维护)
- 组织标签授权:基于组织标签的权限控制(适合企业场景)
KnowFlow 的部署方案:
- K8s:容器编排(自动扩容、自动恢复)
- Prometheus:监控(实时监控、告警)
源码里的问题(❗❗):
- JWT secret 硬编码在代码里
- JWT 没有设置过期时间,或者过期时间太长
- 敏感接口没有限流,容易被攻击
修复方案:
- 用环境变量或 K8s Secret 存储 JWT secret
- 设置合理的过期时间(1 小时)+ 刷新 token 机制
- 加限流(Redis + Lua 脚本)
参考资料:
- Spring Security 官方文档:https://spring.io/projects/spring-security
- JWT 官方文档:https://jwt.io/introduction
- Kubernetes 官方文档:https://kubernetes.io/docs/
- Prometheus 官方文档:https://prometheus.io/docs/
最后更新:2026-06-08 22:15:00