​​​​​​功能详解 01 · 用户注册:从表单到数据库一行
个人主页会编程的土豆欢迎来访作者简介后端学习者❄️个人专栏数据结构与算法数据库leetcode✨那些你一个人走过的夜路终将化作照亮未来的光系列《影院票务 GO》功能详解 · 第 01 篇对应代码代码在这个系列的文章中templates/register.html→static/js/app.js→handlers/auth.go→dao/user.go→utils/password.go数据库sql/schema.sql中users表前置一、背景为什么要有注册影院票务系统TTMS里很多操作必须知道「你是谁」选座、下单要把座位绑到你的账号订单列表只显示自己的票评论、评分要记录发表人。注册就是在系统里新建一条用户记录以后用「用户名 密码」登录。本项目的注册特点前后端分离式交互页面是 HTML 表单提交走JSON API不是传统 form POST 刷新整页。密码绝不存明文每个用户随机8 位盐存MD5(密码盐)。新用户默认顾客role 0管理员只能种子数据或人工改库注册接口不会创建管理员。二、用户视角点「注册」后发生了什么打开http://localhost:8080/register端口以config为准你会看到用户名必填密码必填HTML 限制至少 6 位昵称、手机可选填完点「注册并登录」前端脚本doRegister会阻止表单默认刷新e.preventDefault()把字段打包成 JSONPOST /api/register注册成功后立刻再调POST /api/login自动登录跳转到首页/。若用户名已存在或密码太短浏览器alert弹出后端返回的中文错误信息。三、请求链路总览[浏览器 register.html] │ 用户提交 ▼ [app.js doRegister] │ fetch POST /api/register (JSON body) ▼ [handlers/routes.go] mux.HandleFunc(/api/register, a.APIRegister) ▼ [handlers/auth.go APIRegister] │ 校验参数 → 查重 → 哈希密码 → 组装 User ▼ [dao/user.go CreateUser] │ INSERT INTO users ... ▼ [MySQL users 表] │ 返回 LastInsertId ▼ [utils/json.go OK] → {code:0,message:ok,data:{id:3}} │ ▼ (前端继续) [app.js] POST /api/login → Session → location.href/路由注册在handlers/routes.go第 18 行mux.HandleFunc(/api/register, a.APIRegister)页面路由mux.HandleFunc(/register, a.PageRegister)PageRegister只负责渲染模板不做业务func (a *App) PageLogin(w http.ResponseWriter, r *http.Request) { ... } func (a *App) PageRegister(w http.ResponseWriter, r *http.Request) { a.Render(w, register.html, pageData{Title: 注册, User: a.currentUser(r)}) }四、前端表单如何变成 JSONtemplates/register.html核心form idregForm onsubmitreturn doRegister(event) label用户名input nameusername required //label label密码input namepassword typepassword required minlength6 //label ... /formstatic/js/app.js中doRegisterasync function doRegister(e) { e.preventDefault(); const fd new FormData(e.target); try { await api(/api/register, { method: POST, body: JSON.stringify({ username: fd.get(username), password: fd.get(password), nickname: fd.get(nickname), phone: fd.get(phone), }), }); await api(/api/login, { ... }); // 注册成功后自动登录 location.href /; } catch (err) { alert(err.message); } return false; }公共封装api()做了三件事fetch时带Content-Type: application/jsoncredentials: same-origin—— 为后续登录写 Cookie 做准备解析统一格式{code, message, data}code ! 0就抛错。对应后端utils/json.gotype APIResult struct { Code int json:code Message string json:message Data interface{} json:data,omitempty } func OK(w http.ResponseWriter, data interface{}) { JSON(w, 0, ok, data) } func Fail(w http.ResponseWriter, message string) { JSON(w, 1, message, nil) }设计要点业务失败时 HTTP 状态码仍是 200靠code1区分前端只需看data.code不必处理 4xx/5xx 分支课设简化写法。五、后端 APIRegister逐步拆解完整代码在handlers/auth.go。我们按执行顺序读。5.1 只允许 POSTif r.Method ! http.MethodPost { utils.Fail(w, 方法不允许) return }若有人用浏览器直接访问/api/registerGET会收到 JSON 错误不会误插入数据。5.2 解析 JSON 到匿名结构体var req struct { Username string json:username Password string json:password Nickname string json:nickname Phone string json:phone } if err : utils.DecodeJSON(r, req); err ! nil { utils.Fail(w, 参数错误) return }DecodeJSON读r.Body并json.Decode。字段 tag 的json:username与前端 JSON 键名对应。5.3 参数校验req.Username strings.TrimSpace(req.Username) if req.Username || len(req.Password) 6 { utils.Fail(w, 用户名不能为空密码至少6位) return }去掉用户名首尾空格避免 alice 这种视觉重复账号密码长度6是后端底线前端minlength6是第一道防线后端必须再验防绕过。5.4 用户名唯一性exist, err : dao.GetUserByUsername(req.Username) if err ! nil { utils.Fail(w, err.Error()) return } if exist ! nil { utils.Fail(w, 用户名已存在) return }dao/user.gofunc GetUserByUsername(username string) (*models.User, error) { u : models.User{} err : db.DB.QueryRow( SELECT id,username,password,salt,nickname,phone,role,created_at FROM users WHERE username?, username, ).Scan(...) if errors.Is(err, sql.ErrNoRows) { return nil, nil // 没找到不是错误表示可以注册 } return u, err }sql.ErrNoRows时返回(nil, nil)是 Go database/sql 的常见模式「查无此人」≠ 数据库故障。表结构里还有一层保险username VARCHAR(50) NOT NULL UNIQUE,即使并发两次相同用户名注册第二条 INSERT 也会因唯一索引失败本项目先查再插课设足够高并发应靠数据库约束 事务。5.5 昵称默认值if req.Nickname { req.Nickname req.Username }用户没填昵称时展示名等于登录名。5.6 密码哈希盐 MD5salt : utils.RandomSalt(8) u : models.User{ Username: req.Username, Password: utils.HashPassword(req.Password, salt), Salt: salt, Nickname: req.Nickname, Phone: req.Phone, Role: models.RoleCustomer, // 常量 0 }utils/password.gofunc HashPassword(password, salt string) string { sum : md5.Sum([]byte(password salt)) return hex.EncodeToString(sum[:]) } func RandomSalt(n int) string { const letters abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 // crypto/rand 逐字符随机 ... }为什么要盐若只存MD5(密码)两个用户密码相同则哈希相同攻击者可用彩虹表批量反查。每人不同盐同样密码哈希也不同。种子数据验证方式sql/seed.sql(admin, MD5(CONCAT(admin123, saltadmin)), saltadmin, ...),MySQL 的MD5(CONCAT(...))与 Go 的md5.Sum([]byte(passwordsalt))算法一致。答辩提醒MD5 已不适合生产密码存储应 bcrypt/argon2课设选 MD5 是为了算法简单、与 SQL 种子一致。详见blogs/13-密码与哈希MD5与盐.md。5.7 写入数据库if err : dao.CreateUser(u); err ! nil { utils.Fail(w, 注册失败: err.Error()) return } utils.OK(w, map[string]interface{}{id: u.ID})dao/user.gofunc CreateUser(u *models.User) error { res, err : db.DB.Exec( INSERT INTO users(username,password,salt,nickname,phone,role) VALUES(?,?,?,?,?,?), u.Username, u.Password, u.Salt, u.Nickname, u.Phone, u.Role, ) if err ! nil { return err } u.ID, _ res.LastInsertId() return nil }LastInsertId()把数据库自增主键写回u.ID响应里带给前端前端当前没用 id但 API 设计完整。models.User中密码字段带json:-即使将来把 User 序列化给前端也不会泄露哈希type User struct { Password string json:- Salt string json:- Role int json:role ... }六、数据库表与字段含义sql/schema.sqlCREATE TABLE IF NOT EXISTS users ( id BIGINT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password CHAR(32) NOT NULL COMMENT MD5(passwordsalt), salt VARCHAR(16) NOT NULL, nickname VARCHAR(50) NOT NULL DEFAULT , phone VARCHAR(20) NOT NULL DEFAULT , role TINYINT NOT NULL DEFAULT 0, -- 0顾客 1管理员 created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP );字段注册时谁赋值说明id数据库自增用户唯一标识username用户输入登录名passwordHashPassword32 位十六进制saltRandomSalt(8)明文存储用于登录校验nickname用户或默认用户名页面展示phone用户可选联系方式role固定RoleCustomer0注册不能当管理员created_at数据库默认注册时间七、注册 vs 登录别混淆环节注册/api/register登录/api/login密码处理生成盐 → 哈希 →存入读库盐 → 哈希输入 →比对Session不创建Sessions.Create写 Cookie返回{id}{id, username, nickname, role}注册成功后前端主动调登录用户无感若只注册不登录首页仍显示「登录/注册」链接。登录校验用utils.CheckPasswordfunc CheckPassword(password, salt, hashed string) bool { return HashPassword(password, salt) hashed }同一套HashPassword保证注册与登录算法一致。八、常见错误与排查现象可能原因怎么查alert「参数错误」JSON 格式不对、Body 空浏览器 Network 看 Request Payload「用户名已存在」重复注册SELECT * FROM users WHERE username...「注册失败: …」数据库未启动、DSN 错看main.go启动日志注册成功但未登录第二步 login 失败Network 看/api/login响应密码 5 位也能提交只绕过前端后端应拒绝本项目已校验len 6九、小结页面register.html收集字段JS转 JSON POST 到/api/register。APIRegister校验 → 查重 →RandomSaltHashPassword→CreateUserINSERT。新用户role 固定为 0顾客密码MD5(明文盐)存库明文永不落盘。前端注册成功后自动 login建立 Session下一篇细讲。统一 JSON 响应code/message/data前后端约定清晰。用一句话向学长描述「注册就是 handlers 收 JSONdao 插 users 一行密码先随机盐再 MD5库里只有摘要。」下一篇02-登录退出与Session.md—— 登录如何写 Cookiettms_sidstore/session.go如何在内存里记住你。

相关新闻

目前 Claude / GPT 的订阅建议与反代避坑

目前 Claude / GPT 的订阅建议与反代避坑

半年来在 Claude 和 GPT 的 CLI 上累计消耗了约 30,000$ 用量的 tokens(Claude : GPT 2: 1,Fable 5 出来之后 GPT 用量为 0)。这期间关于模型对比体验的文章断断续续其实写了不少,但 Agent 相关技术和概念迭代太快,新…

2026/7/28 1:27:11 阅读更多 →
HarmonyOS应用开发实战:猫猫大作战-@Extend 的使用

HarmonyOS应用开发实战:猫猫大作战-@Extend 的使用

前言 Extend 装饰器用于为特定组件类型扩展样式方法,与 Styles 的通用属性集合不同,Extend 可以访问组件特有的属性。 本文以「猫猫大作战」的 Text 标题样式为锚点,讲解 Extend 的使用。 提示:本系列不讲 ArkTS 基础语法与环境…

2026/7/28 1:26:11 阅读更多 →
HarmonyOS应用开发实战:猫猫大作战-在 HarmonyOS 应用中,`app.json5` 位于 `AppScope/` 目录下,是整个应用的“全

HarmonyOS应用开发实战:猫猫大作战-在 HarmonyOS 应用中,`app.json5` 位于 `AppScope/` 目录下,是整个应用的“全

前言 在 HarmonyOS 应用中,app.json5 位于 AppScope/ 目录下,是整个应用的“全球身份证“——它定义了应用的唯一标识(bundleName)、版本号、全局图标和标签。系统包管理器和应用市场都依赖这个文件的配置来识别和分发应用。 本…

2026/7/28 1:26:11 阅读更多 →

最新新闻

DeepSeek V4 API成本优化:高峰时段价格策略与实战方案

DeepSeek V4 API成本优化:高峰时段价格策略与实战方案

DeepSeek V4 API 高峰时段价格策略分析与成本优化实战 在AI应用开发过程中,很多开发者都遇到过这样的困扰:白天调用API响应迅速、成本可控,但到了晚上或特定时段,不仅响应变慢,费用还明显上涨。特别是使用DeepSeek V4这类高性能模型时,价格波动对项目预算影响显著。本文将…

2026/7/28 1:34:14 阅读更多 →
深度解析CFC项目:基于cimbar编码的视觉数据传输技术架构

深度解析CFC项目:基于cimbar编码的视觉数据传输技术架构

深度解析CFC项目:基于cimbar编码的视觉数据传输技术架构 【免费下载链接】cfc Demo/test android app for libcimbar. Copy files over the cell phone camera! 项目地址: https://gitcode.com/gh_mirrors/cfc/cfc CameraFileCopy(CFC&#xff09…

2026/7/28 1:34:14 阅读更多 →
如何快速下载国家中小学智慧教育平台电子课本:3分钟搞定PDF教材的完整教程

如何快速下载国家中小学智慧教育平台电子课本:3分钟搞定PDF教材的完整教程

如何快速下载国家中小学智慧教育平台电子课本:3分钟搞定PDF教材的完整教程 【免费下载链接】tchMaterial-parser 国家中小学智慧教育平台 电子课本下载工具,帮助您从智慧教育平台中获取电子课本的 PDF 文件网址并进行下载,让您更方便地获取课…

2026/7/28 1:34:14 阅读更多 →
深度观察 | 2026 木门十大品牌排行榜发布:头部品牌凭实力赢得市场认可

深度观察 | 2026 木门十大品牌排行榜发布:头部品牌凭实力赢得市场认可

行业背景与榜单说明 2026 年,中国木门行业步入高质量发展的深度调整期。随着存量房翻新、改善型住房需求持续释放,叠加绿色家居、全屋定制相关政策的推动,国内木门市场规模保持稳步增长。与此同时,消费需求已从基础的空间遮隔功能…

2026/7/28 1:34:14 阅读更多 →
小学信息科技教学资源开发与实践指南

小学信息科技教学资源开发与实践指南

1. 项目背景与核心价值这套义务教育版小学信息科技全套资料的出现,填补了基础教育阶段系统性教学资源的空白。作为一线教师,我深刻体会到优质教学资源对课堂效率的提升作用。这套资料严格对标国家课程标准,覆盖3-6年级全学段,包含…

2026/7/28 1:34:14 阅读更多 →
【新】5p242基于机器学习的农产品价格数据分析与预测可视化系统31(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_

【新】5p242基于机器学习的农产品价格数据分析与预测可视化系统31(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_

【新】5p242基于机器学习的农产品价格数据分析与预测可视化系统31(设计源文件万字报告讲解)(支持资料、图片参考_相关定制)_ python3.8hadoopdjangospidermysql5.7vue 系统采用Scrapy框架进行数据采集,从惠农网等平台抓取蔬菜、水产品等农产品…

2026/7/28 1:33:13 阅读更多 →

日新闻

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:43 阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑:把几百页的财报、法规、技术手册扔给向量库,问一个具体问题,搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了,要么藏在几十条结果的最下面。语义相似≠真正相关,这个…

2026/7/28 0:00:43 阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营,从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候,每天刷半小时抖音,手动把爆款视频的口播敲进备忘录,一条2分钟的视频得花十来分钟,碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:43 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/27 4:33:59 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/27 6:31:56 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/27 4:01:12 阅读更多 →

月新闻