4--用户注册接口与BCrypt加密
我们已经把用户表创建完毕,接下来便是用户注册与登录的部分
go get -u golang.org/x/crypto/bcrypt加入bcrypt包
一. 统一相应封装
pkg/response/response.go
package response
import (
"github.com/gin-gonic/gin"
)
type Response struct {
Code int `json:"code"`
Msg string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
func Success(c *gin.Context, data interface{}) {
c.JSON(200, Response{
Code: 0,
Msg: "success",
Data: data,
})
}
func Fail(c *gin.Context, code int, msg string) {
c.JSON(200, Response{
Code: code,
Msg: msg,
})
}
二. 用户数据访问层
internal/repository/user.go
package repository
import "github.com/Chuan81/secgo-mall/internal/model"
// CreateUser 创建一个新的用户记录
func CreateUser(user *model.User) error {
return DB.Create(user).Error
}
// GetUserByEmail 根据邮箱查询用户
func GetUserByEmail(email string) (*model.User, error) {
var user model.User
err := DB.Where("email = ?", email).First(&user).Error
if err != nil {
return nil, err
}
return &user, nil
}
// GetUserByPhone 根据手机号查询用户
func GetUserByPhone(phone string) (*model.User, error) {
var user model.User
err := DB.Where("phone = ?", phone).First(&user).Error
if err != nil {
return nil, err
}
return &user, nil
}
// GetUserByUsername 根据用户名查询用户
func GetUserByUsername(username string) (*model.User, error) {
var user model.User
err := DB.Where("username = ?", username).First(&user).Error
if err != nil {
return nil, err
}
return &user, nil
}
三. 请求结构体(DTO)
DTO = Data Transfer Object(数据传输对象)
简单说就是:专门用来接收前端参数的"容器"。
internal/api/handlers/dto/user.go
package dto
// RegisterRequest 定义了用户注册请求的DTO结构体,包含用户名、邮箱、手机号和密码等字段
type RegisterRequest struct {
Username string `json:"username" binding:"required,min=3,max=20"` // 用户名,必填,长度限制为3-20个字符
Email string `json:"email" binding:"required,email"` // 邮箱,必填,必须是有效的邮箱格式
Phone string `json:"phone" binding:"required,e164"` // 手机号,必填,必须符合E.164国际电话号码格式
Password string `json:"password" binding:"required,min=6,max=255"` // 密码,必填,长度限制为6-255个字符
}
四. 用户业务逻辑层
internal/service/user.go
package service
import (
"errors"
"github.com/Chuan81/secgo-mall/internal/api/handlers/dto"
"github.com/Chuan81/secgo-mall/internal/model"
"github.com/Chuan81/secgo-mall/internal/repository"
"golang.org/x/crypto/bcrypt"
)
func Register(req *dto.RegisterRequest) (*model.User, error) {
// 检查用户名是否已存在
if _, err := repository.GetUserByUsername(req.Username); err == nil {
return nil, errors.New("username already exists")
}
// 检查邮箱是否已存在
if _, err := repository.GetUserByEmail(req.Email); err == nil {
return nil, errors.New("email already exists")
}
// 检查手机号是否已存在
if _, err := repository.GetUserByPhone(req.Phone); err == nil {
return nil, errors.New("phone number already exists")
}
// bcrypt 加密密码
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
if err != nil {
return nil, err
}
// 创建用户
user := &model.User{
Username: req.Username,
Email: req.Email,
Phone: req.Phone,
Password: string(hashedPassword),
}
if err := repository.CreateUser(user); err != nil {
return nil, err
}
return user, nil
}
五. 用户控制器
internal/api/handlers/user.go
package handlers
import (
"github.com/Chuan81/secgo-mall/internal/api/handlers/dto"
"github.com/Chuan81/secgo-mall/internal/service"
"github.com/Chuan81/secgo-mall/pkg/response"
"github.com/gin-gonic/gin"
)
func Register(c *gin.Context) {
var req dto.RegisterRequest
// 绑定请求参数到DTO结构体,并进行验证
if err := c.ShouldBindJSON(&req); err != nil {
response.Fail(c, 400, "invalid request parameters: "+err.Error())
return
}
// 调用服务层的注册逻辑
user, err := service.Register(&req)
if err != nil {
response.Fail(c, 500, "registration failed: "+err.Error())
return
}
// 注册成功,返回用户信息(不包含密码)
response.Sucess(c, gin.H{
"uid": user.Uid,
"username": user.Username,
"email": user.Email,
"phone": user.Phone,
"createdAt": user.CreatedAt,
})
}
六. 添加路由
cmd/secgo-mall/main.go
import (
// ... existing imports ...
"github.com/Chuan81/secgo-mall/internal/api/handlers"
)
func main() {
// ... existing code ...
r := gin.Default()
// 注册路由
r.POST("/api/user/register", handlers.Register)
r.GET("/ping", func(c *gin.Context) {
// ...
})
// ... rest of code ...
}
七. 测试
在 Postman 中创建 admin 用户的步骤:
1. 新建请求
Method: POST
URL: http://localhost:8080/api/user/register
2. 配置 Body
在 Body 选项卡中选择 raw,格式选择 JSON,填写:
{
"username": "admin",
"email": "admin@secgo.com",
"phone": "13800000000",
"password": "admin123"
}
3. 发送请求
点击 Send 按钮,预期返回:
{
"code": 0,
"message": "success",
"data": {
"uid": 1,
"username": "admin",
"email": "admin@secgo.com",
"phone": "13800000000",
"createdAt": "2026-04-10T..."
}
}
如果你的注册接口还未实现或者数据库未启动,会返回相应错误。



浙公网安备 33010602011771号