码上问学问代码之理,学编程之道

安全编码要点

全栈课的底线不是功能跑通,是别把用户数据送出去。这一页对应课程标准明确的素质目标—— 「具备安全编码意识(SQL 注入、密码加密、接口鉴权)」。每个要点都用「错误写法 → 正确写法」对照讲, 配合「古典文学网」后端 hiflask 的真实代码位置,学完能直接回项目里自查。

三道门:① SQL 注入是「数据怎么查才不被篡改」;② 密码加密是「用户口令怎么存才偷不走」; ③ 接口鉴权是「谁的请求才算数」。三道门都过,才是能上线的基本盘。

① SQL 注入:永远用参数化

数据怎么查才不被篡改
错在哪:把用户输入拼进 SQL 字符串,攻击者输入 ' OR '1'='1 就能绕过条件、甚至删库。
Python · 错误写法(危险)
# 用 f-string 拼接用户输入 —— 千万别这么写
sql = f"SELECT * FROM users WHERE name = '{username}'"
db.execute(sql)   # username="' OR '1'='1" 时条件永远为真
Python · 正确写法(参数化 / ORM)
# 占位符,参数与 SQL 分离,注入无处下手
sql = "SELECT * FROM users WHERE name = %s"
db.execute(sql, (username,))

# 或直接用 SQLAlchemy ORM(本项目 hiflask 的做法)
User.query.filter_by(name=username).first()
  • 口诀:用户输入永远不可信,要么用占位符,要么走 ORM,绝不用字符串拼接。
  • 本项目后端 hiflask 全程用 SQLAlchemy,天然规避拼接注入。
  • ② 密码加密:明文存储等于送人

    用户口令怎么存才偷不走
    错在哪:把密码原样存进表,一旦数据库泄露,所有账号瞬间裸奔。
    Python · 正确写法(Werkzeug 哈希)
    from werkzeug.security import generate_password_hash, check_password_hash
    
    # 注册:存哈希,不存明文
    pwd_hash = generate_password_hash(raw_password)   # 自带盐值 + pbkdf2/sha256
    
    # 登录:比对哈希,不是比对明文
    if check_password_hash(user.password, raw_password):
        ...   # ✅ 密码正确
  • 哈希是单向的:只能验证「你输的是不是当初那个」,无法反解出原密码。
  • 本项目 sql/hiwen.sql 的种子账号密码为 PUT_HASH_HERE 占位,上线前须替换为真实 generate_password_hash 结果。
  • 绝不在日志、报错、前端里打印明文密码。
  • ③ 接口鉴权:谁的请求才算数

    JWT 签发 / 校验 / 路由守卫
    错在哪:任何接口都放行,等于把「改别人资料、删别人书评」的权限送给陌生人。
    Python · 后端签发与校验 JWT(hiflask)
    # 登录成功签发 token
    token = jwt.encode({"uid": user.id, "exp": now+3600}, SECRET, algorithm="HS256")
    
    # 受保护接口校验 token,取不到 / 过期都拒绝
    payload = jwt.decode(token, SECRET, algorithms=["HS256"])  # 抛异常即 401
    uid = payload["uid"]
  • 前端路由守卫:Vue Router 的 beforeEach 里检查是否有合法 token,无则跳登录页(本项目 hivue 已封装)。
  • 最小权限:删书评等接口须校验「是不是本人发的」,不能只认 token 就放行任意 id。
  • JWT 密钥放 .env,别硬编码进仓库。
  • ④ CORS 与文件上传安全

    容易被忽略的两道缝

    CORS 白名单

    后端跨域别图省事写 allow_origins=["*"]。开发期放开,生产期只列前端域名白名单,避免任意站点调你的接口。

    上传安全

    头像上传要校验类型、限制大小、用 uuid4 随机文件名(本项目已做)。绝不一上来就 save(request.file) 用原文件名。

    密钥不入代码

    数据库密码、JWT 密钥、云存储 key 一律进 .env 并加入 .gitignore,代码里只读环境变量。

    三道门自查清单(上线前逐项打勾)

    📝 本节自测

    做完点「检查本节」看解析与得分;做错可重做。