Skip to content

Commit b21eae8

Browse files
committed
login and register
1 parent 46e1c23 commit b21eae8

File tree

12 files changed

+272
-11
lines changed

12 files changed

+272
-11
lines changed

api/controller/common/common.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ type CommonController struct {
1616

1717
func init() {
1818
c := &CommonController{}
19-
commGroup := router.GetWebRouter().Group("/v1/common")
19+
r := router.GetWebRouterGroup()
20+
commGroup := r.Group("/common")
2021
commGroup.GET("/getSystemDate", c.GetSystemDate)
2122
commGroup.GET("/getDictionaryData", c.getDictionaryData)
2223
commGroup.GET("/getAllSupportCityList", c.GetAllSupportCityList)

api/controller/user/user.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,39 @@ package user
33
import (
44
"github.com/gin-gonic/gin"
55
"wow-admin/api/router"
6+
"wow-admin/model/dto"
7+
"wow-admin/service"
8+
"wow-admin/utils"
69
"wow-admin/utils/result"
710
)
811

912
type UserController struct {
13+
userService service.UserService
1014
}
1115

1216
func init() {
1317
u := &UserController{}
14-
loginGroup := router.GetWebRouter().Group("v1/user")
15-
loginGroup.GET("getUserInfo", u.getUserInfo)
18+
base := router.GetWebRouterGroup()
19+
base.POST("/login", u.login)
20+
base.POST("/register", u.register)
21+
22+
userRouter := base.Group("/user")
23+
userRouter.GET("getUserInfo", u.getUserInfo)
24+
}
25+
26+
// 后台登录
27+
func (c *UserController) login(ctx *gin.Context) {
28+
loginReq := utils.BindValidJson[dto.Login](ctx)
29+
30+
loginVO, code := c.userService.Login(ctx, loginReq.Username, loginReq.Password)
31+
32+
result.SendData(ctx, code, loginVO)
33+
}
34+
35+
func (c *UserController) register(ctx *gin.Context) {
36+
registerReq := utils.BindValidJson[dto.Register](ctx)
37+
code := c.userService.Register(registerReq)
38+
result.SendCode(ctx, code)
1639
}
1740

1841
func (c *UserController) getUserInfo(ctx *gin.Context) {

api/middleware/auth.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
func AuthLogin() gin.HandlerFunc {
1212
return func(c *gin.Context) {
13+
1314
utils.Logger.Info(c.Request.URL.Path)
1415
requestPath := c.Request.URL.Path
1516
needLogin := ignoreRoute(requestPath)
@@ -63,13 +64,14 @@ func AuthLogin() gin.HandlerFunc {
6364
}
6465
}
6566

66-
/*
67-
*
68-
白名单路由
69-
*/
67+
// 白名单路由
7068
func ignoreRoute(requestPath string) bool {
71-
if strings.HasPrefix(requestPath, "/v1/common") {
72-
return true
69+
// return true
70+
whiteList := []string{"/api/common", "/api/login", "/api/register"}
71+
for _, val := range whiteList {
72+
if strings.HasPrefix(requestPath, val) {
73+
return true
74+
}
7375
}
7476
return false
7577
}

api/router/router.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func InitAndStartWebServer(ctx context.Context, debug bool, wait *utils.WaitGrou
8282
ctx: ctx,
8383
}
8484
_defaultWebServer.Start()
85-
utils.Logger.Info(global.SERVER_NAME+" server started at %s ...", zap.String("backPort", backPort))
85+
utils.Logger.Info(global.SERVER_NAME + " server started at http://localhost" + backPort)
8686
wait.Wrap(func() {
8787
select {
8888
case <-ctx.Done():
@@ -94,3 +94,7 @@ func InitAndStartWebServer(ctx context.Context, debug bool, wait *utils.WaitGrou
9494
func GetWebRouter() *gin.Engine {
9595
return _defaultWebRouter
9696
}
97+
98+
func GetWebRouterGroup() *gin.RouterGroup {
99+
return _defaultWebRouter.Group("/api")
100+
}

dao/base.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package dao
22

33
import (
44
"errors"
5-
65
"gorm.io/gorm"
76
)
87

model/RBAC.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package model
22

3+
import "time"
4+
5+
/**
6+
Role-Based Access Control
7+
*/
8+
39
// 菜单
410
type Menu struct {
511
Universal `mapstructure:",squash"`
@@ -13,3 +19,15 @@ type Menu struct {
1319
KeepAlive int8 `gorm:"type:tinyint(1);default:1" json:"keep_alive"`
1420
Redirect string `gorm:"type:varchar(50);comment:跳转路径" json:"redirect"`
1521
}
22+
23+
// 用户账户信息
24+
type UserAuth struct {
25+
Universal
26+
UserInfoId int `gorm:"" json:"userInfoId"`
27+
Username string `gorm:"type:varchar(50);comment:用户名" json:"username"`
28+
Password string `gorm:"type:varchar(100)" json:"password"`
29+
LoginType int `gorm:"type:tinyint(1);comment:登录类型" json:"loginType"`
30+
IpAddress string `gorm:"type:varchar(20);comment:登录IP地址" json:"ipAddress"`
31+
IpSource string `gorm:"type:varchar(50);comment:IP来源" json:"ip_source"`
32+
LastLoginTime time.Time `gorm:"comment:上次登录时间" json:"LastLoginTime"`
33+
}

model/vo/user.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package vo
2+
3+
import "time"
4+
5+
// 登录VO
6+
type LoginVO struct {
7+
ID int `json:"id"`
8+
UserInfoId int `json:"userInfoId"`
9+
Username string `json:"username"`
10+
LastLoginTime time.Time `json:"last_login_time"`
11+
LoginType int `json:"login_type"`
12+
Token string `json:"token"`
13+
}

service/user.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package service
2+
3+
import (
4+
"github.com/gin-gonic/gin"
5+
"time"
6+
"wow-admin/dao"
7+
"wow-admin/model"
8+
"wow-admin/model/dto"
9+
"wow-admin/model/vo"
10+
"wow-admin/utils"
11+
"wow-admin/utils/result"
12+
)
13+
14+
type UserService struct {
15+
}
16+
17+
// 后台用户登录
18+
func (s *UserService) Login(c *gin.Context, username string, password string) (loginVO vo.LoginVO, code int) {
19+
userAuth := dao.GetOne(model.UserAuth{}, "username", username)
20+
if userAuth.ID == 0 {
21+
return loginVO, result.ERROR_USER_NOT_EXIST
22+
}
23+
24+
return loginVO, code
25+
}
26+
27+
// 注册用户
28+
func (s *UserService) Register(userDto dto.Register) (code int) {
29+
30+
if exist := checkUserExistByUsername(userDto.Username); exist {
31+
return result.ERROR_USER_NAME_USED
32+
}
33+
34+
dao.Create(&model.UserAuth{
35+
Username: userDto.Username,
36+
Password: utils.Encryptor.BcryptHash(userDto.Password),
37+
LoginType: 1,
38+
LastLoginTime: time.Now(),
39+
})
40+
return result.OK
41+
}
42+
43+
func checkUserExistByUsername(username string) bool {
44+
user := dao.GetOne(model.UserAuth{}, "username = ?", username)
45+
return user.ID != 0
46+
}

utils/encrypt.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package utils
2+
3+
import (
4+
"crypto/md5"
5+
"encoding/base64"
6+
"encoding/hex"
7+
"fmt"
8+
"golang.org/x/crypto/bcrypt"
9+
"golang.org/x/crypto/scrypt"
10+
"log"
11+
"math/rand"
12+
"time"
13+
)
14+
15+
type _encrypt struct{}
16+
17+
var Encryptor = new(_encrypt)
18+
19+
// 使用 scrypt 对密码进行加密生成一个哈希值
20+
func (*_encrypt) ScryptHash(password string) string {
21+
const KeyLen = 10
22+
// 随便写
23+
salt := []byte{13, 14, 5, 2, 0, 55, 22, 11}
24+
25+
hashPwd, err := scrypt.Key([]byte(password), salt, 1<<15, 8, 1, KeyLen)
26+
if err != nil {
27+
log.Fatal("加密失败: ", err)
28+
}
29+
return base64.StdEncoding.EncodeToString(hashPwd)
30+
}
31+
32+
// 使用 scrypt 对比 明文密码 和 数据库中哈希值
33+
func (c *_encrypt) ScryptCheck(password, hash string) bool {
34+
return c.ScryptHash(password) == hash
35+
}
36+
37+
// 使用 bcrypt 对密码进行加密生成一个哈希值
38+
func (*_encrypt) BcryptHash(password string) string {
39+
bytes, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
40+
return string(bytes)
41+
}
42+
43+
// 使用 bcrypt 对比 明文密码 和 数据库中哈希值
44+
func (*_encrypt) BcryptCheck(password, hash string) bool {
45+
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
46+
return err == nil
47+
}
48+
49+
// MD5 加密
50+
func (*_encrypt) MD5(str string, b ...byte) string {
51+
h := md5.New()
52+
h.Write([]byte(str))
53+
return hex.EncodeToString(h.Sum(b))
54+
}
55+
56+
// 验证码
57+
func (*_encrypt) ValidateCode() string {
58+
return fmt.Sprintf("%06v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))
59+
}
60+
61+
// TODO
62+
func UUID() string {
63+
return ""
64+
}

utils/gin_context.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package utils
2+
3+
import (
4+
"github.com/gin-gonic/gin"
5+
"go.uber.org/zap"
6+
"net/http"
7+
"wow-admin/utils/result"
8+
)
9+
10+
// 参数合法性校验
11+
func Validate(c *gin.Context, data any) {
12+
validMsg := Validator.Validate(data)
13+
if validMsg != "" {
14+
result.ReturnJSON(c, http.StatusOK, result.ERROR_INVALID_PARAM, validMsg, nil)
15+
panic(nil)
16+
}
17+
}
18+
19+
// Json 绑定
20+
func BindJson[T any](c *gin.Context) (data T) {
21+
if err := c.ShouldBindJSON(&data); err != nil {
22+
Logger.Error("ShouldBindJSON", zap.Error(err))
23+
panic(result.ERROR_REQUEST_PARAM)
24+
}
25+
return
26+
}
27+
28+
// Json 绑定验证 + 合法性校验
29+
func BindValidJson[T any](c *gin.Context) (data T) {
30+
if err := c.ShouldBindJSON(&data); err != nil {
31+
Logger.Error("ShouldBindJSON", zap.Error(err))
32+
panic(result.ERROR_REQUEST_PARAM)
33+
}
34+
Validate(c, &data)
35+
return data
36+
}

utils/gorms.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ func InitMyQLDB() *gorm.DB {
2929

3030
log.Println("MySQL 连接成功")
3131

32+
// _ = db.AutoMigrate(&model.UserAuth{})
33+
3234
sqlDB, _ := db.DB()
3335

3436
// 设置连接池中的最大闲置连接

utils/validator.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package utils
2+
3+
import (
4+
"github.com/go-playground/locales/zh_Hans_CN"
5+
unTrans "github.com/go-playground/universal-translator"
6+
"github.com/go-playground/validator/v10"
7+
zhTrans "github.com/go-playground/validator/v10/translations/zh"
8+
"reflect"
9+
)
10+
11+
type ValidateUtil struct {
12+
}
13+
14+
var Validator = new(ValidateUtil)
15+
16+
var (
17+
uni *unTrans.UniversalTranslator
18+
validate *validator.Validate
19+
)
20+
21+
func (v *ValidateUtil) Validate(data any) string {
22+
// 实例化验证对象
23+
validate = validator.New()
24+
25+
// 翻译器
26+
trans := v.validateTransInit(validate)
27+
28+
err := validate.Struct(data)
29+
if err != nil {
30+
for _, e := range err.(validator.ValidationErrors) {
31+
return e.Translate(trans)
32+
}
33+
}
34+
35+
return ""
36+
}
37+
38+
// 数据验证翻译器
39+
func (*ValidateUtil) validateTransInit(validate *validator.Validate) unTrans.Translator {
40+
// 万能翻译器,保存所有的语言环境和翻译数据
41+
uni = unTrans.New(zh_Hans_CN.New())
42+
// 翻译器
43+
trans, _ := uni.GetTranslator("zh_Hans_CN")
44+
//验证器注册翻译器
45+
zhTrans.RegisterDefaultTranslations(validate, trans)
46+
47+
// 读取 Tag 中的 label 标签为字段的翻译
48+
validate.RegisterTagNameFunc(func(field reflect.StructField) string {
49+
return field.Tag.Get("label")
50+
})
51+
52+
return trans
53+
}

0 commit comments

Comments
 (0)