j
jaryue
V1
2023/04/23阅读:12主题:默认主题
项目1 登录功能 day6(事务控制,实现登录注册功能,接口文档)
接口文档:
https://www.apifox.cn/apidoc/shared-7bff1720-a9e6-4bae-8fe8-abf60694ebc4
功能实现
-
图片验证码接口实现 -
登录接口实现 -
注册接口实现 -
改密接口完善 -
事务操作中间件
// 事务中间件,如果用户响应出错,则数据库回滚到响应之前的状态
func DBMid(db *sql.DB) gee7.HandlerFunc {
return func(ctx *gee7.Context) {
// 开始事务
tx, err := db.Begin()
if err != nil {
ctx.FailJson(401, err.Error())
return
}
// 调用下一个处理器
ctx.Next()
// 如果响应出现错误,回滚事务
if ctx.StatusCode >= 400 {
tx.Rollback()
return
}
// 提交事务
tx.Commit()
}
}
接口实现:
log/main.go
//获取图片验证码
r.GET("/verifypic", funcmod.Picverfi(db))
//注册1,1. 图片验证,;2. 发送邮件验证码
r.POST("/login1", func(ctx *gee7.Context) {
data := funcmod.Login1data{}
//读取用户传入的json数据
err = ctx.Getjson(&data)
if err != nil {
ctx.FailJson(410, "解析数据错误"+err.Error())
return
}
if funcmod.Validatedata(data.Email) {
ctx.FailJson(402, "email不合理,请规范填写数据")
}
//验证图片验证码是否正确
err = funcmod.Verifypiccode(db, data.PicID, data.PicCode)
if err != nil {
ctx.FailJson(401, "验证码错误"+err.Error())
return
}
_, err = funcmod.GetuserId(db, data.Email)
if err == nil {
ctx.FailJson(410, "账号已经注册了")
return
}
rand.Seed(time.Now().UnixNano())
// 生成100000到999999之间的随机数,作为验证码
verification := rand.Intn(899999) + 100000
//储存验证码到数据库
err = funcmod.InsertVerification(db, &funcmod.EmailVerificationCode{
Email: data.Email,
Verification: verification})
if err != nil {
ctx.FailJson(401, "发送失败,稍后再试"+err.Error())
return
}
//发送验证码
err = funcmod.SendEmail(dailer, data.Email, verification)
if err != nil {
ctx.FailJson(401, "发送失败"+err.Error())
return
}
ctx.JSON(200, gee7.H{
"msg": "ok",
})
})
//login2:1.验证验证码,;2. 向用户列表插入数据
r.POST("/login2", func(ctx *gee7.Context) {
data := funcmod.Logindata{}
//读取用户传入的json数据
err = ctx.Getjson(&data)
if err != nil {
ctx.FailJson(410, "解析数据错误"+err.Error())
return
}
if funcmod.Validatedata(data.Name) {
ctx.FailJson(402, "name不合理,请规范填写数据")
return
}
if funcmod.Validatedata(data.Password) {
ctx.FailJson(402, "password不合理,请规范填写数据")
return
}
//验证用户验证码是否正确
err = funcmod.Verify(db, data.Email, data.Verification)
if err != nil {
ctx.FailJson(401, "验证码错误"+err.Error())
return
}
//插入用户数据
id, err := funcmod.AddLogindata(db, &data)
if err != nil {
ctx.FailJson(401, err.Error())
} else {
// 添加操作信息
err = funcmod.Addoperation(db, id, "注册成功")
if err != nil {
ctx.JSON(401, gee7.H{
"msg": err.Error(),
})
} else {
ctx.JSON(200, gee7.H{
"msg": "成功",
})
}
}
})
r.POST("/signuppsw", signup.SigninBypassword(db))
r.POST("/signupemail1", signup.SigninByEmail1(db, dailer))
r.POST("/signupemail2", signup.SigninByEmail2(db))
//修改密码
//密码改密
r.POST("/resetpaswbypasw", funcmod.ResetpaswBypassword(db))
//验证码改密
r.POST("/resetpaswbyemail1", funcmod.ResetpaswByEmail1(db, dailer))
r.POST("/resetpaswbyemail2", funcmod.ResetpaswByEmail2(db))
登录功能封装:
funcmod/signin.go
func SigninBypassword(db *sql.DB) gee7.HandlerFunc {
return func(ctx *gee7.Context) {
var data funcmod.Signupbypasw
err := ctx.Getjson(&data)
if err != nil {
ctx.Fail(401, err.Error())
}
// 验证图片验证码是否正确
err = funcmod.Verifypiccode(db, data.PicID, data.PicCode)
if err != nil {
ctx.FailJson(401, "验证码错误"+err.Error())
return
}
//验证成功,获取id信息
id, err := funcmod.GetuserId(db, data.Email)
if err != nil {
ctx.Fail(401, err.Error())
return
}
// 验证登录密码
err = funcmod.Verifypassword(db, id, data.Password)
if err != nil {
ctx.Fail(401, "密码错误:"+err.Error())
return
}
//密码验证成功:
idcode := uuid.New().String() //随机生成唯一标识符,作为身份码
signindata := funcmod.SignInData{
ID: id,
IDCode: idcode,
}
// 插入用户登录信息,登陆成功
if err = funcmod.InsertSignInData(db, &signindata); err != nil {
ctx.Fail(401, err.Error())
funcmod.Addoperation(db, signindata.ID, "signin失败"+err.Error())
} else {
funcmod.Addoperation(db, signindata.ID, "signin成功")
//登录成功返回id与身份码
ctx.JSON(200, gee7.H{
"signindata": signindata,
"msg": "ok",
})
}
}
}
// 登录第一步:1. 图片验证,;2. 发送邮件验证码
func SigninByEmail1(db *sql.DB, dialer *gomail.Dialer) gee7.HandlerFunc {
return func(ctx *gee7.Context) {
data := funcmod.Signupbyemail1{}
//读取用户传入的json数据
err := ctx.Getjson(&data)
if err != nil {
ctx.FailJson(410, "解析数据错误"+err.Error())
return
}
if funcmod.Validatedata(data.Email) {
ctx.FailJson(402, "email不合理,请规范填写数据")
}
//验证图片验证码是否正确
err = funcmod.Verifypiccode(db, data.PicID, data.PicCode)
if err != nil {
ctx.FailJson(401, "验证码错误"+err.Error())
return
}
_, err = funcmod.GetuserId(db, data.Email)
if err != nil {
ctx.FailJson(410, "账号未注册注册,请先注册")
return
}
rand.Seed(time.Now().UnixNano())
// 生成100000到999999之间的随机数,作为验证码
verification := rand.Intn(899999) + 100000
//储存验证码到数据库
err = funcmod.InsertVerification(db, &funcmod.EmailVerificationCode{
Email: data.Email,
Verification: verification})
if err != nil {
ctx.FailJson(401, "发送失败,稍后再试"+err.Error())
return
}
//发送验证码
err = funcmod.SendEmail(dialer, data.Email, verification)
if err != nil {
ctx.FailJson(401, "邮箱错误"+err.Error())
return
}
ctx.JSON(200, gee7.H{
"msg": "ok",
})
}
}
// 完成验证码登录功能:验证验证码是否正确,插入数据
func SigninByEmail2(db *sql.DB) gee7.HandlerFunc {
return func(ctx *gee7.Context) {
var data funcmod.Signupbyemail2
err := ctx.Getjson(&data)
if err != nil {
ctx.Fail(401, err.Error())
}
// 验证用户邮箱验证码是否正确
err = funcmod.Verify(db, data.Email, data.Verification)
if err != nil {
ctx.FailJson(401, "验证码错误"+err.Error())
return
}
//验证成功,获取id信息
id, err := funcmod.GetuserId(db, data.Email)
if err != nil {
ctx.Fail(401, err.Error())
return
}
idcode := uuid.New().String() //随机生成唯一标识符,作为身份码
signindata := funcmod.SignInData{
ID: id,
IDCode: idcode,
}
// 插入用户登录信息,登陆成功
if err = funcmod.InsertSignInData(db, &signindata); err != nil {
ctx.Fail(401, err.Error())
funcmod.Addoperation(db, signindata.ID, "signin失败"+err.Error())
} else {
funcmod.Addoperation(db, signindata.ID, "signin成功")
//登录成功返回id与身份码
ctx.JSON(200, gee7.H{
"signindata": signindata,
"msg": "ok",
})
}
}
}
改密功能封装:+数据校验
// 用于检验用户传入的数据是否合理
// 正则表达式,匹配长度为 8-50 的 ASCII 字符串
// 合理为false不合理为true
func Validatedata(password string) bool {
regex := regexp.MustCompile(`^[[:ascii:]]{3,40}$`)
return !regex.MatchString(password)
}
func ResetpaswBypassword(db *sql.DB) gee7.HandlerFunc {
return func(ctx *gee7.Context) {
data := ResetpaswData{}
//读取用户传入的json数据
err := ctx.Getjson(&data)
if err != nil {
ctx.FailJson(410, "解析数据错误"+err.Error())
return
}
if Validatedata(data.Password) {
ctx.FailJson(402, "password不合理,请规范填写数据")
return
}
if Validatedata(data.Newpassword) {
ctx.FailJson(402, "newpassword不合理,请规范填写数据")
return
}
//身份验证
err = SignInVerification(db, &data.SignInData)
if err != nil {
ctx.FailJson(401, err.Error())
return
}
//验证密码
err = Verifypassword(db, data.SignInData.ID, data.Password)
if err != nil {
ctx.FailJson(401, err.Error())
return
}
//修改密码
err = Changepassword(db, data.ID, data.Newpassword)
if err != nil {
ctx.FailJson(401, err.Error())
return
}
// 添加操作信息
err = Addoperation(db, data.ID, "改密成功")
if err != nil {
ctx.JSON(401, gee7.H{
"msg": err.Error(),
})
}
ctx.JSON(200, gee7.H{
"msg": "ok",
})
}
}
// 验证改密第一步:1. 图片验证,;2. 发送邮件验证码
func ResetpaswByEmail1(db *sql.DB, dialer *gomail.Dialer) gee7.HandlerFunc {
return func(ctx *gee7.Context) {
data := ResetpaswbyemailData1{}
//读取用户传入的json数据
err := ctx.Getjson(&data)
if err != nil {
ctx.FailJson(410, err.Error())
}
//验证图片验证码是否正确
err = Verifypiccode(db, data.PicID, data.PicCode)
if err != nil {
ctx.FailJson(401, "图片验证码错误"+err.Error())
return
}
// 验证成功:获取用户邮箱
emial, err := GetuserEmail(db, data.ID)
if err != nil {
ctx.FailJson(410, "未找到邮箱信息,请联系管理员"+err.Error())
}
rand.Seed(time.Now().UnixNano())
// 生成100000到999999之间的随机数,作为验证码
verification := rand.Intn(899999) + 100000
//储存验证码到数据库
err = InsertVerification(db, &EmailVerificationCode{
Email: emial,
Verification: verification})
if err != nil {
ctx.FailJson(401, "发送失败,稍后再试"+err.Error())
return
}
//发送验证码
err = SendEmail(dialer, emial, verification)
if err != nil {
ctx.FailJson(401, "邮箱错误"+err.Error())
return
}
ctx.JSON(200, gee7.H{
"msg": "ok",
})
}
}
// 完成验证码改密功能:验证验证码是否正确,插入数据
func ResetpaswByEmail2(db *sql.DB) gee7.HandlerFunc {
return func(ctx *gee7.Context) {
var data ResetpaswbyemailData2
err := ctx.Getjson(&data)
if err != nil {
ctx.Fail(401, err.Error())
}
if Validatedata(data.Newpassword) {
ctx.FailJson(402, "password不合理,请规范填写数据")
return
}
// 验证用户邮箱验证码是否正确
err = Verify(db, data.Email, data.Verification)
if err != nil {
ctx.FailJson(401, "验证码错误"+err.Error())
return
}
//验证成功,获取id信息
id, err := GetuserId(db, data.Email)
if err != nil {
ctx.Fail(401, err.Error())
return
}
//修改密码
err = Changepassword(db, id, data.Newpassword)
if err != nil {
ctx.FailJson(401, err.Error())
return
}
// 添加操作信息
err = Addoperation(db, id, "改密成功")
if err != nil {
ctx.JSON(401, gee7.H{
"msg": err.Error(),
})
}
ctx.JSON(200, gee7.H{
"msg": "ok",
})
}
}
所有文件代码
funcmod/data.go
封装请求与响应需要的数据类型
package funcmod
import "time"
// 邮箱验证码信息(验证码需要真人验证之后再发送)(登录时可以直接使用)
type EmailVerificationCode struct {
Email string `json:"email"`
Verification int `json:"verification"`
}
// 注册传入信息2,邮箱验证码信息+用户基本信息
type Logindata struct {
EmailVerificationCode `json:"emailverificationcode"`
Name string `json:"name"`
Password string `json:"password"`
}
// 注册传入信息1,id为图片的唯一标识符,code为用户传入 的图片验证码, Email为需要发送验证邮件的邮箱
type Login1data struct {
PicID string `json:"picid"`
PicCode []byte `json:"piccode"`
Email string `json:"email"`
}
// 身份验证信息(id+身份码)
type SignInData struct {
ID int `json:"id"`
IDCode string `json:"idcode"`
}
// 操作信息列表
type OperationRecord struct {
ID int `json:"id"`
Behavior string `json:"behavior"`
Time int `json:"time"`
}
// 改密接受信息
type ResetpaswData struct {
SignInData `json:"signindata"`
Password string `json:"password"`
Newpassword string `json:"newpassword"`
}
// 改密接受信息1:图片验证+身份验证
type ResetpaswbyemailData1 struct {
SignInData `json:"signindata"`
PicID string `json:"picid"`
PicCode []byte `json:"piccode"`
}
// 验证码验证+新密码
type ResetpaswbyemailData2 struct {
EmailVerificationCode `json:"emailverificationcode"`
Newpassword string `json:"newpassword"`
}
// 验证码数据模型
type VerificationCode struct {
PicID string `json:"picid"`
PicCode []byte `json:"piccode"`
Image string `json:"image"`
CreatedAt time.Time `json:"created_at"`
}
// 密码登录信息(图片验证信息+邮箱+密码)
type Signupbypasw struct {
PicID string `json:"picid"`
PicCode []byte `json:"piccode"`
Email string `json:"email"`
Password string `json:"password"`
}
// 发送验证码时上传的信息(图片验证信息+身份验证信息)
type Signupbyemail1 struct {
PicID string `json:"picid"`
PicCode []byte `json:"piccode"`
Email string `json:"email"`
}
// 使用邮箱验证码登录时上传的信息(图片验证信息+身份验证信息)
type Signupbyemail2 struct {
EmailVerificationCode
}
funcmod/sqloperate.go
封装所有的数据库操作
package funcmod
//对数据库操作的所有函数
import (
"database/sql"
"fmt"
"time"
)
// 添加操作信息,向表OperationRecord(操作列表)添加
func Addoperation(db *sql.DB, id int, operation string) error {
_, err := db.Exec("insert into OperationRecord (id,behavior,time) VALUES (?, ?, ?)", id, operation, time.Now().Unix())
if err != nil {
return err
}
return nil
}
// 获取:表OperationRecord(操作列表)的数据
func Getoperations(db *sql.DB, id int) ([]OperationRecord, error) {
rows, err := db.Query("SELECT behavior, time FROM OperationRecord WHERE id = ?", id)
if err != nil {
return nil, err
}
defer rows.Close()
result := []OperationRecord{}
for rows.Next() {
p := &OperationRecord{ID: id}
err = rows.Scan(&p.Behavior, &p.Time)
if err != nil {
return result, err
}
result = append(result, *p)
}
if err := rows.Err(); err != nil {
return result, err
}
return result, nil
}
// user表------------------------------------------------------------------
// add:向user(注册列表)添加元素
func AddLogindata(db *sql.DB, logindata *Logindata) (int, error) {
r, err := db.Exec("insert into user (name,password,Email) VALUES (?, ?, ?)", logindata.Name, encryptPassword(logindata.Password), logindata.Email)
if err != nil {
return 0, err
}
id, err := r.LastInsertId()
return int(id), err
}
// ((id是操作用的,不是给用户登录用的))
// get:获取:向user(注册列表)获取id,登陆成功,获取id
func GetuserId(db *sql.DB, email string) (int, error) {
id := -1
err := db.QueryRow("SELECT id FROM user WHERE Email = ?", email).Scan(&id)
if err != nil {
return -1, err
}
return id, nil
}
// get:获取:向user(注册列表)获取email(改密时查Email,不能由用户传入Email,)
func GetuserEmail(db *sql.DB, id int) (string, error) {
Email := ""
err := db.QueryRow("SELECT Email FROM user WHERE id = ?", id).Scan(&Email)
if err != nil {
return "", err
}
return Email, nil
}
// 查:验证user(注册列表)密码
func Verifypassword(db *sql.DB, id int, password string) error {
count := 0
err := db.QueryRow("SELECT COUNT(*) FROM user WHERE id = ? AND password = ? ", id, encryptPassword(password)).Scan(&count)
if err != nil {
return err
}
return nil
}
// 改:修改:user(注册列表)密码
func Changepassword(db *sql.DB, id int, newpassword string) error {
_, err := db.Exec("UPDATE user SET password = ? WHERE id = ?", newpassword, id)
if err != nil {
return err
}
return nil
}
// -SignInlist--------------------------------------------------------------------
// 查:SignIn查询身份验证功能:传入SignInData
func SignInVerification(db *sql.DB, signInData *SignInData) error {
// 查询身份认证码是否正确
var expirationTime int64 //储存过期时间
err := db.QueryRow("SELECT ExpirationTime FROM SignInList WHERE id = ? AND IDcode = ?", signInData.ID, signInData.IDCode).Scan(&expirationTime)
if err != nil {
return fmt.Errorf("非法访问")
}
// 验证身份认证码是否过期
if time.Now().Unix() > expirationTime {
return fmt.Errorf("身份验证过期,请重新登陆")
}
// 验证成功.更新身份认证码的过期时间
_, err = db.Exec("UPDATE SignInList SET ExpirationTime = ? WHERE id = ? AND IDcode = ?", time.Now().Unix()+30*60, signInData.ID, signInData.IDCode)
if err != nil {
return err
}
return nil
}
// 增:向登录列表插入信息
func InsertSignInData(db *sql.DB, data *SignInData) error {
// 准备SQL语句
stmt, err := db.Prepare("REPLACE INTO SignInList (id, IDcode, ExpirationTime) VALUES (?, ?, ?)")
if err != nil {
return err
}
defer stmt.Close()
// 执行插入操作
result, err := stmt.Exec(data.ID, data.IDCode, time.Now().Unix()+30*60)
if err != nil {
return err
}
// 输出插入结果
_, err = result.RowsAffected()
if err != nil {
return err
}
return nil
}
// delete:删除登录信息; 登出删除登录列表元素
func Deletesignindata(db *sql.DB, id int) error {
_, err := db.Exec("DELETE FROM SignInList WHERE id = ?", id)
if err != nil {
return err
}
return nil
}
// VerificationCode(验证码储存库)----------------------------------------------------------
// 查: 验证验证码
func Verify(db *sql.DB, email string, verification int) error {
// 查询验证码是否正确
var expirationTime int64 //储存过期时间
//代表已经验证过
db.Exec("UPDATE VerificationCode SET password = ? WHERE Email = ?", 1, email)
err := db.QueryRow("SELECT ExpirationTime FROM VerificationCode WHERE Email = ? AND Verification = ?", email, verification).Scan(&expirationTime)
if err != nil {
return fmt.Errorf("验证码错误" + err.Error())
}
// 验证身份认证码是否过期
if time.Now().Unix() > expirationTime {
return fmt.Errorf("过期")
}
return nil
}
// 增:验证码了列表插入信息
func InsertVerification(db *sql.DB, data *EmailVerificationCode) error {
// 准备SQL语句
stmt, err := db.Prepare("REPLACE INTO VerificationCode (Email, Verification, ExpirationTime, time) VALUES (?, ?, ?, ?)")
if err != nil {
return err
}
defer stmt.Close()
// 执行插入操作
_, err = stmt.Exec(data.Email, data.Verification, time.Now().Unix()+5*60, 0)
if err != nil {
return err
}
return nil
}
// get:获取:验证次数,重发验证码0无,1有
func GetuVerificationtime(db *sql.DB, email string) (int, error) {
t := -1
err := db.QueryRow("SELECT time FROM user WHERE Email = ?", email).Scan(&t)
if err != nil {
return -1, err
}
return t, nil
}
// // ----------------------------------------------------------
// func Insertuserdata(db *sql.DB, data Logindata) error {
// // 准备SQL语句
// stmt, err := db.Prepare("INSERT INTO user (Email, name, password) VALUES (?, ?, ?)")
// if err != nil {
// return err
// }
// defer stmt.Close()
// // 执行插入操作
// _, err = stmt.Exec(data.Email, data.Name, encryptPassword(data.Password))
// if err != nil {
// return err
// }
// return nil
// }
//
// 图片验证码验证操作:用户传入图片id(唯一标识符发送图片信息时给的),+验证码
func Verifypiccode(db *sql.DB, id string, code []byte) error {
var createdAt []uint8
err := db.QueryRow("SELECT created_at FROM verification_codes WHERE id = ? AND code = ?", id, code).Scan(&createdAt)
if err != nil {
return err
}
created_ats := string(createdAt)
created_at, err := time.Parse("2006-01-02 15:04:05", created_ats)
if err != nil {
return err
}
// 删除验证码
db.Exec("DELETE FROM verification_codes WHERE id = ?", id)
if time.Now().Unix() > created_at.Unix()+5*60 { //时效5分钟
return fmt.Errorf("验证码过期")
}
return nil
}
func scanTime(v interface{}) (t time.Time, err error) {
switch u := v.(type) {
case time.Time:
return u, nil
case []byte:
return time.Parse("2006-01-02 15:04:05", string(u))
case string:
return time.Parse("2006-01-02 15:04:05", u)
default:
return t, fmt.Errorf("unable to parse time: %v", v)
}
}
opensql.go
打开数据库操作
package funcmod
import "database/sql"
// 打开数据库
func Opensql() (*sql.DB, error) {
// 打开数据库连接
return sql.Open("mysql", "xxx:xxxxx@tcp(127.0.0.1:3306)/login")
}
密码加密储存于查询
package funcmod
import (
"crypto/sha256"
"encoding/hex"
)
func encryptPassword(password string) string {
// 将字符串类型的密码转换为字节类型
passwordBytes := []byte(password)
// 创建SHA-256哈希对象
sha256Hash := sha256.New()
// 将密码字节数据传入哈希对象
sha256Hash.Write(passwordBytes)
// 获取哈希值的字节数据
hashBytes := sha256Hash.Sum(nil)
// 将字节数据转换为十六进制字符串
hashString := hex.EncodeToString(hashBytes)
// 返回十六进制字符串类型的哈希值
return hashString
}
定义部分中间件函数于操作函数(改密,检验用户输入,图片发送,登录状态检验)
package funcmod
import (
"bytes"
"database/sql"
"encoding/base64"
"fmt"
"goweb/day7/gee7"
"math/rand"
"net/http"
"regexp"
"time"
"github.com/dchest/captcha"
"github.com/google/uuid"
"gopkg.in/gomail.v2"
)
// 身份验证中间件(是否处于登录状态)
func Authentication(db *sql.DB) gee7.HandlerFunc {
return func(ctx *gee7.Context) {
var signInData SignInData
err := ctx.Getjson(&signInData)
if err != nil {
ctx.Fail(401, err.Error())
}
if err = SignInVerification(db, &signInData); err != nil {
ctx.Fail(401, "失败:"+err.Error())
} else {
ctx.String(200, "成功")
}
}
}
// 发送图片验证码图片中间件(用户提交请求时)
func Picverfi(db *sql.DB) gee7.HandlerFunc {
return func(ctx *gee7.Context) {
// 生成验证码
id := uuid.New().String() //生成唯一标识符
code := captcha.RandomDigits(4)
img := captcha.NewImage(id, code, captcha.StdWidth, captcha.StdHeight)
// 生成验证码
var buf bytes.Buffer
_, err := img.WriteTo(&buf)
if err != nil {
ctx.FailJson(401, "出错了,点击重试")
}
// 将验证码和图片存储到数据库中
encodedImage := base64.StdEncoding.EncodeToString(buf.Bytes())
verificationCode := VerificationCode{PicCode: code, Image: encodedImage, CreatedAt: time.Now()}
_, err = db.Exec("INSERT INTO verification_codes (id, code, image, created_at) VALUES (?, ?, ?, ?)", id, verificationCode.PicCode, verificationCode.Image, verificationCode.CreatedAt)
if err != nil {
ctx.FailJson(http.StatusInternalServerError, "Internal Server Error:"+err.Error())
return
}
// 返回图片与唯一标识符
ctx.JSON(200, gee7.H{
"picid": id,
"png": verificationCode.Image,
})
fmt.Printf("id=%#v\ncode=%d", id, code)
}
}
// 用于检验用户传入的数据是否合理
// 正则表达式,匹配长度为 8-50 的 ASCII 字符串
// 合理为false不合理为true
func Validatedata(password string) bool {
regex := regexp.MustCompile(`^[[:ascii:]]{3,40}$`)
return !regex.MatchString(password)
}
func ResetpaswBypassword(db *sql.DB) gee7.HandlerFunc {
return func(ctx *gee7.Context) {
data := ResetpaswData{}
//读取用户传入的json数据
err := ctx.Getjson(&data)
if err != nil {
ctx.FailJson(410, "解析数据错误"+err.Error())
return
}
if Validatedata(data.Password) {
ctx.FailJson(402, "password不合理,请规范填写数据")
return
}
if Validatedata(data.Newpassword) {
ctx.FailJson(402, "newpassword不合理,请规范填写数据")
return
}
//身份验证
err = SignInVerification(db, &data.SignInData)
if err != nil {
ctx.FailJson(401, err.Error())
return
}
//验证密码
err = Verifypassword(db, data.SignInData.ID, data.Password)
if err != nil {
ctx.FailJson(401, err.Error())
return
}
//修改密码
err = Changepassword(db, data.ID, data.Newpassword)
if err != nil {
ctx.FailJson(401, err.Error())
return
}
// 添加操作信息
err = Addoperation(db, data.ID, "改密成功")
if err != nil {
ctx.JSON(401, gee7.H{
"msg": err.Error(),
})
}
ctx.JSON(200, gee7.H{
"msg": "ok",
})
}
}
// 验证改密第一步:1. 图片验证,;2. 发送邮件验证码
func ResetpaswByEmail1(db *sql.DB, dialer *gomail.Dialer) gee7.HandlerFunc {
return func(ctx *gee7.Context) {
data := ResetpaswbyemailData1{}
//读取用户传入的json数据
err := ctx.Getjson(&data)
if err != nil {
ctx.FailJson(410, err.Error())
}
//验证图片验证码是否正确
err = Verifypiccode(db, data.PicID, data.PicCode)
if err != nil {
ctx.FailJson(401, "图片验证码错误"+err.Error())
return
}
// 验证成功:获取用户邮箱
emial, err := GetuserEmail(db, data.ID)
if err != nil {
ctx.FailJson(410, "未找到邮箱信息,请联系管理员"+err.Error())
}
rand.Seed(time.Now().UnixNano())
// 生成100000到999999之间的随机数,作为验证码
verification := rand.Intn(899999) + 100000
//储存验证码到数据库
err = InsertVerification(db, &EmailVerificationCode{
Email: emial,
Verification: verification})
if err != nil {
ctx.FailJson(401, "发送失败,稍后再试"+err.Error())
return
}
//发送验证码
err = SendEmail(dialer, emial, verification)
if err != nil {
ctx.FailJson(401, "邮箱错误"+err.Error())
return
}
ctx.JSON(200, gee7.H{
"msg": "ok",
})
}
}
// 完成验证码改密功能:验证验证码是否正确,插入数据
func ResetpaswByEmail2(db *sql.DB) gee7.HandlerFunc {
return func(ctx *gee7.Context) {
var data ResetpaswbyemailData2
err := ctx.Getjson(&data)
if err != nil {
ctx.Fail(401, err.Error())
}
if Validatedata(data.Newpassword) {
ctx.FailJson(402, "password不合理,请规范填写数据")
return
}
// 验证用户邮箱验证码是否正确
err = Verify(db, data.Email, data.Verification)
if err != nil {
ctx.FailJson(401, "验证码错误"+err.Error())
return
}
//验证成功,获取id信息
id, err := GetuserId(db, data.Email)
if err != nil {
ctx.Fail(401, err.Error())
return
}
//修改密码
err = Changepassword(db, id, data.Newpassword)
if err != nil {
ctx.FailJson(401, err.Error())
return
}
// 添加操作信息
err = Addoperation(db, id, "改密成功")
if err != nil {
ctx.JSON(401, gee7.H{
"msg": err.Error(),
})
}
ctx.JSON(200, gee7.H{
"msg": "ok",
})
}
}
发送邮件功能
package funcmod
import (
"fmt"
"gopkg.in/gomail.v2"
)
// 使用gomail库创建SMTP客户端
func CreatDialer() *gomail.Dialer {
return gomail.NewDialer("smtp.qq.com", 465, "xxxxxxxxx", "xxxxxxx") //AuthCode为邮箱的授权码
}
func SendEmail(dialer *gomail.Dialer, to string, verification int) error {
// 发送邮件的QQ邮箱地址
qqEmail := "xxxxxxxxxxxxx"
// 创建邮件消息
message := gomail.NewMessage()
message.SetHeader("From", qqEmail)
message.SetHeader("To", to)
message.SetHeader("Subject", "验证码")
message.SetBody("text/plain", fmt.Sprintf("验证码:%d", verification))
// 发送邮件消息
err := dialer.DialAndSend(message)
if err != nil {
panic(err)
}
return nil
}
main.go
所有功能接口实现
package main
import (
"fmt"
"goweb/day7/gee7"
"goweb/logindata/funcmod"
"goweb/logindata/signup"
"math/rand"
"time"
)
func main() {
r := gee7.New()
db, err := funcmod.Opensql()
if err != nil {
fmt.Printf("数据库出错=%#v\n", err)
return
}
defer db.Close()
r.Use(funcmod.DBMid(db))
//连接邮箱
dailer := funcmod.CreatDialer()
//获取图片验证码
r.GET("/verifypic", funcmod.Picverfi(db))
//注册1,1. 图片验证,;2. 发送邮件验证码
r.POST("/login1", func(ctx *gee7.Context) {
data := funcmod.Login1data{}
//读取用户传入的json数据
err = ctx.Getjson(&data)
if err != nil {
ctx.FailJson(410, "解析数据错误"+err.Error())
return
}
if funcmod.Validatedata(data.Email) {
ctx.FailJson(402, "email不合理,请规范填写数据")
}
//验证图片验证码是否正确
err = funcmod.Verifypiccode(db, data.PicID, data.PicCode)
if err != nil {
ctx.FailJson(401, "验证码错误"+err.Error())
return
}
_, err = funcmod.GetuserId(db, data.Email)
if err == nil {
ctx.FailJson(410, "账号已经注册了")
return
}
rand.Seed(time.Now().UnixNano())
// 生成100000到999999之间的随机数,作为验证码
verification := rand.Intn(899999) + 100000
//储存验证码到数据库
err = funcmod.InsertVerification(db, &funcmod.EmailVerificationCode{
Email: data.Email,
Verification: verification})
if err != nil {
ctx.FailJson(401, "发送失败,稍后再试"+err.Error())
return
}
//发送验证码
err = funcmod.SendEmail(dailer, data.Email, verification)
if err != nil {
ctx.FailJson(401, "发送失败"+err.Error())
return
}
ctx.JSON(200, gee7.H{
"msg": "ok",
})
})
//login2:1.验证验证码,;2. 向用户列表插入数据
r.POST("/login2", func(ctx *gee7.Context) {
data := funcmod.Logindata{}
//读取用户传入的json数据
err = ctx.Getjson(&data)
if err != nil {
ctx.FailJson(410, "解析数据错误"+err.Error())
return
}
if funcmod.Validatedata(data.Name) {
ctx.FailJson(402, "name不合理,请规范填写数据")
return
}
if funcmod.Validatedata(data.Password) {
ctx.FailJson(402, "password不合理,请规范填写数据")
return
}
//验证用户验证码是否正确
err = funcmod.Verify(db, data.Email, data.Verification)
if err != nil {
ctx.FailJson(401, "验证码错误"+err.Error())
return
}
//插入用户数据
id, err := funcmod.AddLogindata(db, &data)
if err != nil {
ctx.FailJson(401, err.Error())
} else {
// 添加操作信息
err = funcmod.Addoperation(db, id, "注册成功")
if err != nil {
ctx.JSON(401, gee7.H{
"msg": err.Error(),
})
} else {
ctx.JSON(200, gee7.H{
"msg": "成功",
})
}
}
})
r.POST("/signuppsw", signup.SigninBypassword(db))
r.POST("/signupemail1", signup.SigninByEmail1(db, dailer))
r.POST("/signupemail2", signup.SigninByEmail2(db))
//修改密码
//密码改密
r.POST("/resetpaswbypasw", funcmod.ResetpaswBypassword(db))
//验证码改密
r.POST("/resetpaswbyemail1", funcmod.ResetpaswByEmail1(db, dailer))
r.POST("/resetpaswbyemail2", funcmod.ResetpaswByEmail2(db))
// 登出
r.POST("/signout", func(ctx *gee7.Context) {
data := funcmod.SignInData{}
//读取用户传入的json数据
err = ctx.Getjson(&data)
if err != nil {
ctx.FailJson(410, "解析数据错误"+err.Error())
return
}
//身份验证
err = funcmod.SignInVerification(db, &data)
if err != nil {
ctx.FailJson(401, err.Error())
return
}
//删除登录列表信息
err = funcmod.Deletesignindata(db, data.ID)
if err != nil {
ctx.JSON(401, gee7.H{
"msg": err.Error(),
})
}
err = funcmod.Addoperation(db, data.ID, "登出成功")
if err != nil {
ctx.JSON(401, gee7.H{
"msg": err.Error(),
})
} else {
ctx.JSON(200, gee7.H{
"msg": "ok",
})
}
})
// 获取操作信息
r.POST("/getoperations", func(ctx *gee7.Context) {
data := funcmod.SignInData{}
//读取用户传入的json数据
err = ctx.Getjson(&data)
if err != nil {
ctx.FailJson(410, "解析数据错误"+err.Error())
return
}
err = funcmod.SignInVerification(db, &data)
if err != nil {
ctx.FailJson(401, err.Error())
return
}
r, err := funcmod.Getoperations(db, data.ID)
if err != nil {
ctx.FailJson(401, err.Error())
return
}
ctx.JSON(200, gee7.H{
"operations": r,
"msg": "ok",
})
})
r.Run(":8888")
}
作者介绍
j
jaryue
V1