按问题类别组织,每题给出参考答案 + 可能追问。
加 ⭐ 的是高频必问题,加 ⚠️ 的是论文里有坑的题。
第一类:技术选型类(必问)
⭐ Q1:为什么选 Django?
答:Django 是"全家桶"框架,自带 ORM、Admin 后台、用户认证、表单处理这些东西,不用重复造轮子,开发效率高。Flask 太轻量,订单、用户、画稿这些模块自己搭脚手架太费时间。Spring Boot 性能好但学习曲线陡,Python 生态对接支付宝 SDK 也更方便。对一个毕业设计来说,Django 在开发效率和稳定性上是平衡得最好的。
⭐ Q2:为什么用 Vue 而不是 React?
答:Vue 中文文档完善、模板语法接近 HTML,对单人开发友好。Ant Design Vue 组件库可以直接拿来用,不用从零写 UI。React 也可以,但 Vue 的双向绑定和单文件组件让我能更快出原型。
Q3:为什么选 MySQL 不用 MongoDB?
答:画稿交易场景里有很强的关联关系——用户、订单、画稿、设计师之间是结构化数据,订单还涉及金额,需要 ACID 保证一致性。MongoDB 适合非结构化或高并发写入的日志类数据,这个场景不合适。
⭐ Q4:JWT 和 Session 的区别,为什么选 JWT?
答:
- Session 是有状态的:服务器存 session 数据,客户端只存 sessionID。多服务器要做共享。
- JWT 是无状态的:所有信息都在 token 里,服务器只验签名。
选 JWT 是因为前后端分离架构下,无状态更利于水平扩展,跨域更友好。
第二类:安全相关(高频)
⭐ Q5:JWT 被盗用怎么办?
答:几个层面防护:
- HTTPS 传输:防止中间人抓包
- 设置较短过期时间(比如 2 小时),配合 refresh token 续签
- 签名密钥保密:放环境变量,不进代码库
- 敏感操作(提现等)加二次校验
论文目前是基础实现,生产环境会加 refresh token 机制。
Q6:密码怎么存的?为什么不存明文?
答:用 Django 的 make_password 加密存储,底层是 PBKDF2-SHA256 + 盐哈希。登录时用 check_password 校验。
明文存储一旦数据库泄露用户密码全暴露,且很多用户多平台同密码,风险更大。
Q7:怎么防 SQL 注入?
答:用 Django ORM,所有查询参数化,框架层面已经防住了。如果用原生 SQL 必须参数化查询,不能字符串拼接。
Q8:怎么防 XSS?
答:
- 前端 Vue 默认对
{{ }}插值做 HTML 转义 - 后端 Django 模板默认转义
- 用户输入的画稿描述如果允许富文本,需要白名单过滤标签
Q9:怎么防 CSRF?
答:JWT 方案下 token 放在请求 Header(不是 Cookie),天然不受 CSRF 攻击影响——CSRF 利用的是浏览器自动带 Cookie 的特性。
⭐ Q10:交易系统怎么保障安全?
答:从四个层面来保障:
第一层:身份安全
- JWT 鉴权
- 密码加密存储
- 设计师人工审核
- 角色权限隔离
第二层:传输安全
- HTTPS 加密
- 支付宝接口 RSA 签名验签
- CORS 配置只允许指定域名
第三层:资金安全(最关键)
- 支付宝官方接口处理资金
- 支付回调用支付宝公钥验签
- 订单号做幂等控制
- 余额扣减用数据库事务
- 退款权限只给管理员
- 金额服务端重新计算,不信前端
第四层:行为安全
- ORM 防 SQL 注入
- 转义防 XSS
- JWT 放 Header 免疫 CSRF
- 敏感接口限流
- 操作日志审计
⭐ Q11:加密方法有哪些?
答:项目里加密分三类:
1. 密码存储 —— 哈希加盐(不是真正的加密)
- 算法:PBKDF2 + SHA256
- 过程:随机盐 + 密码 → 哈希 39 万轮 → 入库
- 存储格式:
pbkdf2_sha256$迭代次数$盐$哈希值 - 校验:登录时取出盐做同样运算,比对哈希值
2. 传输加密 —— HTTPS(TLS)
- 浏览器到服务器全链路加密
- 防中间人窃听
3. 支付宝接口 —— RSA 非对称加密 + 数字签名
- 平台和支付宝各有一对密钥
- 平台用平台私钥签名 → 支付宝用平台公钥验签
- 支付宝用支付宝私钥签名 → 平台用支付宝公钥验签
- 必须验签,不验签的话攻击者能伪造支付成功通知
JWT 签名 —— HMAC-SHA256
- 三部分:Header.Payload.Signature
- 注意:Payload 是 Base64 编码不是加密,不要放敏感信息
Q12:对称加密和非对称加密的区别?
答:
- 对称加密(AES、DES):加解密同一个密钥,速度快,问题是密钥分发
- 非对称加密(RSA、ECC):一对密钥,公钥加密私钥解密,速度慢但解决密钥分发
- 实际系统两者结合:用 RSA 协商出 AES 密钥,后续用 AES 通信(HTTPS 就这么干的)
Q13:哈希、加密、编码的区别?
答:
- 编码(Base64):可逆,不是加密,只是格式转换
- 哈希(SHA256):单向不可逆,相同输入得相同输出
- 加密(AES/RSA):可逆,需要密钥才能解密
Q14:为什么不用 MD5 存密码?
答:MD5 已经不安全:
- 碰撞攻击:能找到两个不同输入产生相同哈希
- 速度太快:现代 GPU 每秒能算几十亿次,暴力破解快
- 没有加盐和迭代设计
PBKDF2、bcrypt、scrypt、argon2 故意设计得"慢"来对抗暴力破解。
第三类:业务逻辑类(容易踩坑)
⭐⚠️ Q15:买家余额扣了但卖家加余额失败,钱怎么办?
论文最大的坑,必须诚实回答:
答:目前 pay 函数是顺序执行的,没有用数据库事务保护,确实存在中间步骤失败导致数据不一致的风险。生产环境应该用 @transaction.atomic 装饰器把扣款、加款、改订单状态包在一个事务里,保证要么全成功要么全回滚。这是后续要优化的点。
@transaction.atomic
def pay(self, order_id):
user = User.objects.select_for_update().get(id=user_id)
# ... 扣款、加款、改状态全在事务里
⭐ Q16:高并发下两个人同时买同一张画稿,余额扣了两次怎么办?
答:需要加锁:
- 悲观锁:
select_for_update()在事务里锁住用户余额行 - 乐观锁:余额表加 version 字段,更新时比对
论文当前实现没处理并发,是可优化点。
⭐ Q17:支付宝回调可能被重复通知,会重复加余额吗?
答:支付宝异步通知确实可能重复发。防重的做法:
- 通过
out_trade_no查订单 - 判断订单状态:已经是 PAID 的直接返回 success,不再加余额
论文里 async_notify 没有明确这步幂等判断,是可以补充的。
Q18:支付宝回调是怎么验签的?防伪造?
答:支付宝 SDK 自带 verify 方法,用支付宝公钥对回调参数做 RSA 验签。只有支付宝私钥签的才能通过验签,攻击者伪造不了。
Q19:怎么防止用户改前端的价格直接低价买?
答:服务端永远以数据库里的画稿价格为准。下单接口只接收 draft_id,价格从数据库查出来计算,前端传的金额只用来显示,不参与扣款逻辑。
Q20:画稿被买之后还能被别人买吗?
答:当前设计是可重复售卖——is_outline 字段控制是否在售。如果要做版权独占需要购买后自动下架。这是产品定义层面的选择。
Q21:退款时如果设计师已经把余额提现走了怎么办?
答:当前 return_order 函数会检查 designer.balance < draft.price,余额不够就抛异常退款失败。
生产上应该有"冻结期"——画稿售出后金额先冻结 N 天再可提现,防止退款时无款可退。
第四类:架构 & 设计类
⭐ Q22:为什么前后端分离?
答:
- 职责清晰,前端专注 UI,后端专注业务
- 后端只提供 REST API,可同时支持 Web、小程序、App
- 前后端独立部署、独立迭代
- 前端可以走 CDN 加速
⭐⚠️ Q23:user 表和 designer 表字段几乎一样,为什么分两张?
论文设计上的明显问题,诚实回答:
答:当时考虑设计师有专属属性(认证状态、作品集等)想做扩展,但目前两张表字段确实高度重复,造成数据冗余。
更合理的做法有两种:
- 单 user 表 + role 字段("user"/"designer"/"admin")
- user 主表 + designer_profile 副表,副表只存设计师独有字段
这是后续要重构的地方。
Q24:系统架构是几层?
答:四层
- 用户层:浏览器 + Vue 前端
- Web 应用服务层:Django,分视图层、业务层、数据访问层
- 数据库层:MySQL
- 操作系统层:Linux/Windows
Q25:REST API 设计遵循什么规范?
答:用 HTTP 动词表达操作(GET/POST/PUT/DELETE),URL 用名词复数,状态码用 HTTP 标准(200/400/401/500)。响应统一格式 {code, msg, data}。
第五类:数据库字段类
⭐ Q26:为什么用户 ID 用 bigint?
答:三方面考虑:
1. 容量足够 + 扩展性
- int 4 字节,最大 21 亿;bigint 8 字节,最大 9.2×10¹⁸
- 互联网项目用 bigint 是行业惯例
- 避免后期数据量大了改类型,迁移成本高
2. 性能影响有限
- 现代 CPU 是 64 位,处理 bigint 和 int 速度几乎一样
- 多 4 字节相比 varchar 主键还是快得多
3. 自增主键的优势
- 空间小(8 字节 vs UUID 36 字节)
- InnoDB 友好,自增主键插入永远在 B+ 树末尾,不会页分裂
- 索引效率高,整数比较快
关于 (20):很多人误以为是位数,其实只是显示宽度,配合 ZEROFILL 才有意义。MySQL 8.0.17 之后这个括号已经废弃。
⭐⚠️ Q27:为什么余额、价格、金额用 float?金额不会丢精度吗?
论文最显眼的坑:
答:float 是浮点数,存储金额会有精度问题,比如 0.1 + 0.2 在 float 下不等于 0.3。涉及钱的场景,正确做法是 DECIMAL(10,2)——总共 10 位数字,2 位是小数,最大能存 99999999.99,对画稿交易场景够用。也可以用 bigint 存"分"。
当时没意识到这个问题,是数据库设计上的疏漏,生产环境必须改成 DECIMAL。
Q28:手机号为什么用 varchar 不用 bigint?
答:
- 手机号不参与运算,存数字类型没意义
- 可能有前导 0 或国际区号 "+86",bigint 存不了
- varchar 方便做格式校验和模糊查询
Q29:状态字段(status)为什么用 varchar 不用 int?
答:用字符串是为了可读性——直接看数据就知道是 "pending" 还是 "completed",不用查枚举映射表。
缺点是占空间、可能拼错。更优做法是用 tinyint + 应用层枚举,性能和可读性兼顾。
⚠️ Q30:orders 表既有 status 又有 is_cancel,是不是冗余?
答:您说得对,这两个字段语义重叠。保留 is_cancel 可能是为了快速过滤未取消的订单(避免字符串比较),但加索引到 status 也能解决。如果重做我会去掉 is_cancel,只保留 status。
Q31:为什么不用 UUID 做主键?
答:UUID 优点是分布式场景下不用协调就能生成唯一 ID,但缺点:
- 占空间大:36 字符 vs 8 字节
- 无序性破坏 B+ 树:UUID 插入位置随机,频繁页分裂,写入性能差
- 可读性差
- 索引效率低:字符串比较慢
折中方案是雪花算法(Snowflake)——bigint 类型 + 趋势递增 + 分布式唯一。
Q32:为什么字符集用 utf8mb4 不是 utf8?
答:MySQL 的 utf8 是个历史坑——只支持 3 字节字符,存不了 4 字节字符(emoji、生僻字)。utf8mb4 才是真正的 UTF-8。画稿描述、用户昵称都可能有 emoji,必须用 utf8mb4。
Q33:为什么用 InnoDB 不用 MyISAM?
答:
- InnoDB 支持事务,MyISAM 不支持
- InnoDB 支持外键,MyISAM 不支持
- InnoDB 行锁,MyISAM 表锁,并发性能 InnoDB 好
- MySQL 5.5 之后 InnoDB 已经是默认引擎
Q34:哪些字段加了索引?
答:
user.username:登录时按用户名查orders.user_id:查"我的订单"draft.user_id:查设计师的画稿列表
原则:高频查询条件 + 区分度高的字段加索引,写多读少不加(索引拖慢写入)。
第六类:性能 & 扩展性
Q35:访问量大了怎么办?
答:
- 数据库:读写分离、Redis 缓存热门画稿
- 静态资源:图片 OSS + CDN
- 应用层:Django 多实例 + Nginx 负载均衡
- 接口:分页、字段裁剪
Q36:图片存哪里?大量图片怎么处理?
答:当前 image_url 是字符串路径,文件存服务器本地 media 目录。
生产应该用对象存储(OSS / 七牛),CDN 加速,本地只存 URL。还可以做缩略图自动生成。
Q37:搜索画稿用 LIKE 查询吗?大数据量下慢怎么办?
答:当前是 MySQL LIKE 模糊查询,数据量小没问题。数据量大要换 ElasticSearch 做全文检索,支持分词、相关度排序、高亮。
第七类:测试相关
Q38:测试覆盖率多少?做了哪些测试?
答:论文里主要是功能测试,覆盖了注册、登录、设计师认证、充值、画稿交易等核心流程。还提到性能测试方法(JMeter / Locust)和安全测试方法(SQL 注入、XSS、CSRF),但实际数据没在论文里展开。
Q39:怎么测的支付宝接口?真的付了钱吗?
答:用支付宝沙箱环境——支付宝开放平台提供的测试账号和测试金额,所有调用都是模拟的,不涉及真实资金。
第八类:灵魂拷问类
⭐ Q40:你这个项目和淘宝、Etsy 比有什么优势?
答:不是要替代它们,而是垂直化——专注画稿交易场景:
- 设计师认证机制专门针对画稿创作者
- 交易流程围绕"数字作品授权"设计
- 后期可以做版权保护、AI 推荐这些垂直能力
⭐ Q41:项目最难的部分是什么?
答:支付宝接口对接最难,因为:
- 异步回调机制要理解
- 验签、加密、回调地址配置容易出错
- 沙箱环境配置坑多
⭐ Q42:如果让你重做一遍,会怎么改?
答:
- user 和 designer 合表 + role 字段
- 金额用 DECIMAL
- 交易加事务和并发控制
- 加 Redis 缓存
- 引入消息队列处理异步任务(订单超时自动取消)
- 加评论、评分、推荐算法
⭐ Q43:项目有哪些问题或漏洞?
答(主动暴露 2 个加分):
从设计、安全、性能三个角度都有可优化空间:
设计上
- 金额用 float 应改 DECIMAL
- user 和 designer 表字段冗余
- orders.is_cancel 与 status 重复
安全上
- 交易没加数据库事务
- 支付回调缺少幂等检查
- 没有并发控制
性能上
- 没有 Redis 缓存
- 图片存本地
- 搜索用 LIKE
这些都是可以优化的点,体现了对项目的反思。
Q44:项目独立完成吗?借鉴了什么?
答:参考了开源 Django 电商项目的订单状态机设计、支付宝官方文档的接入流程,UI 用了 Ant Design Vue 现成组件。但业务逻辑、数据库设计、整体架构是独立完成的。
答辩策略
核心原则
- 承认问题 + 给改进方案 > 硬撑
- 老师反感的是不懂装懂,不是不完美
- 主动暴露 1-2 个问题
- 推荐:金额用 float、交易没加事务
- 显得有反思能力,加分项
- 不要把答辩稿背得太死
- 老师一打断就慌
- 理解项目结构 > 背稿子
- 多说"我考虑过 A 和 B 两种方案"
- 体现思考过程
- 比直接给答案更显严谨
- 不要主动暴露的雷区
- 私钥硬编码(不专业)
- 测试覆盖不足(打脸论文测试章节)
- 这些被问到再答
Top 10 必答题清单
把这 10 题答案背熟,覆盖答辩 80% 问题:
| 排名 | 问题 | 关键词 |
|---|---|---|
| 1 | 为什么选 Django/Vue/MySQL | 全家桶、易用、ACID |
| 2 | JWT vs Session | 无状态、水平扩展 |
| 3 | 密码怎么存 | PBKDF2-SHA256 + 盐 |
| 4 | 交易系统怎么保障安全 | 身份/传输/资金/行为四层 |
| 5 | 加密方法 | 哈希/HTTPS/RSA 三类 |
| 6 | 余额扣了卖家加失败怎么办 | 数据库事务(坑) |
| 7 | 支付回调重复怎么办 | 幂等性 + 订单号 |
| 8 | user 和 designer 为什么分两张表 | 承认冗余(坑) |
| 9 | 金额为什么用 float | 承认错误,应改 DECIMAL(坑) |
| 10 | bigint 用户 ID 为什么 | 容量+性能+扩展性 |
紧急救场话术
完全不会答的问题:
"这个问题我之前没有深入考虑过,您说的方向我会下来重点研究/优化。我目前的实现是 XX,可能存在 YY 的不足。"
被指出 bug:
"感谢老师指出,这确实是我没考虑到的点。正确的做法应该是 XX。我会在后续版本中补上这块。"
追问技术细节超出能力:
"这部分我用到的程度是 XX,更深层的原理我还在学习中。能请您指点一下吗?"
把姿态放低,承认不足,比硬编错答案安全得多。

Comments NOTHING