feat(auth+db): 实现注册登录核心逻辑,以及自动建表,用户信息落库
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"gen2d/internal/db"
|
||||
"gen2d/internal/model"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// AuthService 用户认证服务。
|
||||
type AuthService struct {
|
||||
jwtSecret []byte
|
||||
jwtExpire time.Duration
|
||||
}
|
||||
|
||||
// NewAuthService 创建 AuthService 实例。
|
||||
func NewAuthService(jwtSecret string, jwtExpire int64) *AuthService {
|
||||
return &AuthService{
|
||||
jwtSecret: []byte(jwtSecret),
|
||||
jwtExpire: time.Duration(jwtExpire) * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
// Register 注册新用户,密码使用 bcrypt 加密存储。
|
||||
func (s *AuthService) Register(ctx context.Context, username, password, email string) (*model.User, error) {
|
||||
hashed, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user := model.User{
|
||||
Username: username,
|
||||
Password: string(hashed),
|
||||
Email: email,
|
||||
}
|
||||
|
||||
if err := db.DB.WithContext(ctx).Create(&user).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrDuplicatedKey) {
|
||||
return nil, errors.New("用户名已存在")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// Login 校验用户名密码,成功返回 JWT token 及用户信息。
|
||||
func (s *AuthService) Login(ctx context.Context, username, password string) (string, int64, *model.User, error) {
|
||||
var user model.User
|
||||
if err := db.DB.WithContext(ctx).Where("username = ?", username).First(&user).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return "", 0, nil, errors.New("用户名或密码错误")
|
||||
}
|
||||
return "", 0, nil, err
|
||||
}
|
||||
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
|
||||
return "", 0, nil, errors.New("用户名或密码错误")
|
||||
}
|
||||
|
||||
expiresAt := time.Now().Add(s.jwtExpire)
|
||||
claims := jwt.MapClaims{
|
||||
"sub": user.ID,
|
||||
"exp": expiresAt.Unix(),
|
||||
"iat": time.Now().Unix(),
|
||||
}
|
||||
token, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(s.jwtSecret)
|
||||
if err != nil {
|
||||
return "", 0, nil, err
|
||||
}
|
||||
|
||||
return token, int64(s.jwtExpire.Seconds()), &user, nil
|
||||
}
|
||||
Reference in New Issue
Block a user