14.登录模块
# 01.登录CLD
# 1.1 routes/routes.go 处理路由 C
package routes
import (
"gin_bbs/controllers"
"gin_bbs/logger"
"github.com/gin-gonic/gin"
)
func Setup(mode string) *gin.Engine {
if mode == gin.ReleaseMode {
gin.SetMode(gin.ReleaseMode)
}
r := gin.New()
r.Use(logger.GinLogger(), logger.GinRecovery(true))
r.POST("/test", controller.TestHandler)
v1 := r.Group("/api/v1")
// 注册
v1.POST("/signup", controller.SignUpHandler)
// 登录
v1.POST("/login", controller.LoginHandler)
return r
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1.2 controller/user.go 参数校验 C
package controller
import (
"errors"
"fmt"
"gin_bbs/dao/mysql"
"gin_bbs/logic"
"gin_bbs/models"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"go.uber.org/zap"
)
func LoginHandler(c *gin.Context) {
// 1.获取请求参数及参数校验
p := new(models.ParamLogin)
if err := c.ShouldBindJSON(p); err != nil {
// 请求参数有误,直接返回响应
zap.L().Error("Login with invalid param", zap.Error(err))
// 判断err是不是validator.ValidationErrors 类型
errs, ok := err.(validator.ValidationErrors)
if !ok {
ResponseError(c, CodeInvalidParam)
return
}
ResponseErrorWithMsg(c, CodeInvalidParam, removeTopStruct(errs.Translate(trans)))
return
}
// 2.业务逻辑处理
user, err := logic.Login(p)
if err != nil {
zap.L().Error("logic.Login failed", zap.String("username", p.Username), zap.Error(err))
if errors.Is(err, mysql.ErrorUserNotExist) {
ResponseError(c, CodeUserNotExist)
return
}
ResponseError(c, CodeInvalidPassword)
return
}
// 3.返回响应
ResponseSuccess(c, gin.H{
"user_id": fmt.Sprintf("%d", user.UserID), // id值大于1<<53-1 int64类型的最大值是1<<63-1
"user_name": user.Username,
"token": user.Token,
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 1.3 models/params.go 校验结构体 C
package models
// ParamLogin 登录请求参数
type ParamLogin struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 1.4 logic/user.go 业务逻辑 L
package logic
import (
"gin_bbs/dao/mysql"
"gin_bbs/models"
"gin_bbs/pkg/jwt"
)
func Login(p *models.ParamLogin) (user *models.User, err error) {
user = &models.User{
Username: p.Username,
Password: p.Password,
}
// 传递的是指针,就能拿到user.UserID
if err := mysql.Login(user); err != nil {
return nil, err
}
// 生成JWT
token, err := jwt.GenToken(user.UserID, user.Username)
if err != nil {
return
}
user.Token = token
return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 1.5 models/user.go 表模型 D
package models
type User struct {
UserID int64 `db:"user_id"`
Username string `db:"username"`
Password string `db:"password"`
Token string
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 1.6 dao/mysql/user.go 数据库 D
package mysql
import (
"crypto/md5"
"database/sql"
"encoding/hex"
"gin_bbs/models"
)
func Login(user *models.User) (err error) {
oPassword := user.Password // 用户登录的密码
sqlStr := `select user_id, username, password from user where username=?`
err = db.Get(user, sqlStr, user.Username)
if err == sql.ErrNoRows {
return ErrorUserNotExist
}
if err != nil {
// 查询数据库失败
return err
}
// 判断密码是否正确
password := encryptPassword(oPassword)
if password != user.Password {
return ErrorInvalidPassword
}
return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 02.登录接口测试
# 2.1 postman测试登录接口
- http://127.0.0.1:8080/api/v1/login
{
"username":"lisi",
"password": "123456"
}
1
2
3
4
2
3
4
上次更新: 2024/3/13 15:35:10