本文用到的包有
github.com/oswaldoooo/octools@v1.1
golang.org/x/crypto/bcrypt
github.com/gin-gonic/gin
最终我们会实现
三个文件负责三个功能
package server
import "github.com/gin-gonic/gin"
func StartServer() {
engine := gin.Default()
stumanager := engine.Group("/manager/student")//创建一个学生管理功能的group,后面做的业务只要是这个范畴的都扔给这个组
engine.LoadHTMLGlob("/Users/oswaldo/dev/golang/newstart/templates/*")//加载模版目录,最后一个*是指目录下全部模版文件
stumanager.POST("/login", Login)//用户在提交登录表单过后,对此反应的方法
stumanager.GET("/login", LoginPage)//用户浏览器直接进的登录页面
stumanager.GET("/regis", RegisisterUserPage)//用户浏览器直接进的注册页面
stumanager.POST("/regis", RegisterUser)//用户提交注册表单过后,对此进行反应的方法
engine.Run(":8001")
}
注册页面逻辑很简单,你提交ID,用户名,密码,后端拿到这些信息后,先查看id是否在当前数据库存在,若存在那这肯定是注册不了的,不存在就直接把相关信息写入数据库,密码写入前用bcrypt加个密再写。这里数据库操作是octools提前封装过的,就不需要去自己手动写老久了
package server
import (
"errors"
"fmt"
"github.com/gin-gonic/gin"
"golang.org/x/crypto/bcrypt"
)
func RegisterUser(ctx *gin.Context) {
//获取这里的基本讯息,id,password,name
id := ctx.PostForm("id")
password := ctx.PostForm("password")
name := ctx.PostForm("name")
userid := &struct{ Id string }{}//先预先定义struct,而且里面fileid一定要大写!!!,不然mysql取出来的数据是放不进去的
var err error
err = usrservice.dbcon.Get(userid, "id", id, "id")//这里的四个参数分别是你数据库取出来的数据放置的容器,数据库查询数据时匹配的参数名,和参数名需对应的值,最后一个id指的是只取id,这句方法相当于select id from tablename where id="your_id_content"
fmt.Println("error>>", err)
if err != nil {
if len(id) > 0 {
res, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)//bcrypt加密,后面可通过它自带的方法对比出是不是和原内容一样,所以不必担心怎么把它解密出来的问题
err = usrservice.dbcon.InsertEasily(map[string]string{"id": id, "name": name, "password": string(res)})//简单的解释:insert into tablename (id,name,password)values('your_id_content','your_name_content','your_password_content')
} else {
err = errors.New("id is empty")
}
}
var code int = 200
data := gin.H{}
if err == nil {
data = gin.H{"status": "regis success"}
} else {
data = gin.H{"status": err}
}
ctx.HTML(code, "regisister.html", data)
}
func RegisisterUserPage(ctx *gin.Context) {
ctx.HTML(200, "regisister.html", nil)
}
数据库控制器注册(需要提前导入github.com/oswaldoooo/octools/database)
type UserService struct {
dbcon *database.DbController
}
var usrservice = NewUserService("user_info", "test:123456@tcp(localhost:3306)/lab")
func NewUserService(tablename, db_url string) *UserService {
return &UserService{dbcon: database.New(tablename, db_url)}
}
登录逻辑
简单粗暴,先看id存不存在,存在=>再看密码对不对的上,对的上,登录成功,上面有一个有问题就返回登录失败
type Student struct {
Id string
Name string
Password string
// ClassName string
}
func Login(ctx *gin.Context) {
//获取前端输入的登录讯息
id := ctx.PostForm("studentid")
pwd := ctx.PostForm("password")
var code int
data := gin.H{}
code = 200
fmt.Printf("accept info id %v,password %v\n", id, pwd)
//控制器为空就是数据库连接出问题了
if usrservice.dbcon != nil {
student := new(Student)
//不写入参数默认获得匹配的全部列(因为咋数据库一共就3个列,这里就默认让它输出匹配的全部列了,如果你的数据库并没完全输出全部列的话,这里后面可加参数声明输出哪些列)
err := usrservice.dbcon.Get(student, "id", id)
if err == nil {
fmt.Println("get student info>>", student) //debugline
err = bcrypt.CompareHashAndPassword([]byte(student.Password), []byte(pwd))//这里就是前文说的hash对比,不需要将你的密码解密来比
}
if err == nil {
data = gin.H{"msg": fmt.Sprintf("Hello,%v", student.Name)}
} else {
data = gin.H{"msg": err}
}
} else {
data = gin.H{"msg": "connect to database failed"}
}
ctx.HTML(code, "greet.html", data)
}
//log in page
func LoginPage(ctx *gin.Context) {
ctx.HTML(200, "login.html", nil)
}
关于octools/database数据库详细操作可参考
github