局部总结的开篇废话
写招新平台之前,写一些小的demo来练手,熟悉整体的框架和思路
但是学业繁重,主要眷顾大学课内的知识巩固,然后一边写算法竞赛的题目,网络编程这边在抽时间研究
这个demo是分成很多阶段来写的,逐渐完善一些初级的功能,所以总结也是写代码之余偶尔写写,并没有专门来整理
然后整理的这些总结呢,是一些自己觉得有意义的点(只是对个人有帮助,对大家仅供参考),个人想写一写自己在
编程时遇到的一些东西,而总结的内容呢,当然也只能是某个部分、不系统的内容…
因为是从零基础开始学习用golang写网站后台,所以代码仅仅是入门功能的实现,也只是记录自己学习路上的一点点经验
递进验证思路
这个部分呢,是因为前端同学希望做成渐进式的验证过程,也就是在一个路由中(/findpwdHandler)进行逐步验证
- 第一次验证:username和phonenum (需正确)
- 第二次验证:question和answer (需正确)
- 第三次:进行原始密码的修改(确认密码要一致)
那么我在传JSON形式字符串时,就一定要理清代码逻辑,验证成功时才进入下一级验证,而传JSON时千万不要传多了!
效果
代码解释
检索时用到MySQL表中的不完整数据
我写过一个总结,在多个数据的MySQL表格中对部分数据进行检索的方法
(链接:检索MySQL表格不完全数据的小贴士)
所以在开始就定义了一些变量名,而我们知道,在golang语言中,为初始化的变量赋值为零值(也就是说这里的空字符串),但是呢…空字符串通过POST请求读入后端,是按照数据库搜索通过处理的,所以这个时候我多加了一次判断结构,也就是说对刚开始定义(遍历MySQL需要用)但是未赋具体值的变量进行判断,如果是空字符串,就别传JSON了,传了就多了,等到后面进入第二次验证的时候再传!
var password string
var question string
var answer string
username := c.PostForm("username")
phonenum := c.PostForm("phonenum")
fmt.Println("username:", username)
fmt.Println("phonenum:", phonenum)
第一次验证username和phonenum
//核心思想:这些没有赋予具体值的变量,按零值搜索通过处理
err = db.QueryRow("select *from msg where username=? and phonenum=?", username, phonenum).Scan(&username, &password, &phonenum, &question, &answer)
第二次验证question和answer
第二次传密保问题和密保答案是在第一次验证通过的基础上进行的,而为了第一次不接受到第二次验证的JSON(因为第二次需要再传数据下来),我们进行空字符串的判断即可:
question = c.PostForm("question")
answer = c.PostForm("answer")
fmt.Println("question:", question)
fmt.Println("answer:", answer)
if question != "" && answer != "" {
...
}
不管怎么验证,都只是代码逻辑思路上的变化,其实本质都是进行MySQL数据库的查找实现,加这个功能的时候其实也没有什么新鲜感,一步一步写下去就OK了
第三步修改密码
最后我定义了newpwd confirm变量,修改密码用到的是MySQL的UPDATE函数,将表格中的数据替换,并不需要写入一个新的行列
stmt, _ := db.Prepare("UPDATE msg SET password=? WHERE username=?")
cg, _ := stmt.Exec(newpwd, temp)
_, err := cg.RowsAffected()
实现的思路就是以上了,关键点也写了处理,就是写总结的内容看上去挺混乱的…也没啥分点,就将就看看了
相对独立关系和关联
- 相对独立:在第一次的验证时,后端收到前端的数据,验证通过后,给前端返回JSON,前端进行页面的动画跳转,而不关后端的事了。进入第二次验证时,再重复第一次的流程,后端收数据,验证,返回JSON,第三次同理。所以说两次验证+改密码的过程是相对独立的,我想清楚这一点之后,果断删除了自己嵌套了四五层的循环结构,在/findpwdHandler中写了三个独立的部分!
- 关联:因为变量需要在一开始定义,所以每一次查询会受到影响,也就是空字符当做查找到该数据处理,这时我们就要加空字符的判断!如果是空字符就不要把JSON传了(还没到你的回合呢)
- 一些处理方法:由于相对独立的关系,到最后修改密码时,我们收不到第一次验证输入的用户名,怎么办呢???解决方法就是我让前端再传一次username过来,也就是下面见到的页面
POSTMAN 测试
下面是MySQL数据库:
找到需要修改密码的一栏:
第一次验证:
第二次验证:
重置密码
加上了确认密码,相同才行:
上面这样就时不可行的,下面的情况可以实现:
检查数据库
ok,这样就实现了 忘记密码并修改密码 的功能,思路并不复杂,细节其实也不多,一步一步仔细写就可以实现…更多总结待续…
实属健忘症,都要发布了才想起来代码忘记粘上来:
//gin重构过的代码
func findpwdHandler(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*")
db, err := sql.Open("mysql", "ZWX568:20010225@/user?charset=utf8")
if err != nil {
fmt.Println(">>> fail to connect to db <<<")
}
defer db.Close()
fmt.Println(">>> succeed to connect to db <<<")
var res result
fmt.Println(">>> findpwd function <<<")
var password string
var question string
var answer string
username := c.PostForm("username")
phonenum := c.PostForm("phonenum")
fmt.Println("username:", username)
fmt.Println("phonenum:", phonenum)
var temp string = username
if username != "" && phonenum != "" {
err = db.QueryRow("select *from msg where username=? and phonenum=?", username, phonenum).Scan(&username, &password, &phonenum, &question, &answer)
if err != nil {
fmt.Println(">>> 1:find pwd fail <<<")
res.Msg = "findno1"
c.JSON(http.StatusOK, res)
} else {
fmt.Println(">>> 1:find pwd ok <<<")
res.Msg = "findok1"
c.JSON(http.StatusOK, res)
}
}
fmt.Println(">>> 2:start <<<")
question = c.PostForm("question")
answer = c.PostForm("answer")
fmt.Println("question:", question)
fmt.Println("answer:", answer)
if question != "" || answer != "" {
err = db.QueryRow("select *from msg where question=? and answer=?", question, answer).Scan(&username, &password, &phonenum, &question, &answer)
if err != nil {
fmt.Println(">>> 2:find pwd fail <<<")
res.Msg = "findno2"
c.JSON(http.StatusOK, res)
} else {
fmt.Println(">>> 2:find pwd ok <<<")
res.Msg = "findok2"
c.JSON(http.StatusOK, res)
}
}
fmt.Println(">>> change pwd start <<<")
newpwd := c.PostForm("newpwd")
confirm := c.PostForm("confirm")
if newpwd == "" || confirm == "" {
return
}
fmt.Println("newpwd:", newpwd)
fmt.Println("confirm:", confirm)
if newpwd == confirm {
fmt.Println("username:", temp)
stmt, _ := db.Prepare("UPDATE msg SET password=? WHERE username=?")
cg, _ := stmt.Exec(newpwd, temp)
_, err := cg.RowsAffected()
var res result
if err != nil {
res.Msg = "ChangeNO"
c.JSON(http.StatusOK, res)
fmt.Println(">>> Fail to change pwd <<<")
} else {
res.Msg = "ChangeOK"
c.JSON(http.StatusOK, res)
fmt.Println(">>> Change pwd successfully <<<")
}
} else if newpwd != confirm {
res.Msg = "differ"
c.JSON(http.StatusOK, res)
}
}