|
|
|
package service
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"gofaster/internal/auth/model"
|
|
|
|
"gofaster/internal/auth/repository"
|
|
|
|
|
|
|
|
"github.com/golang-jwt/jwt/v5"
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
|
|
)
|
|
|
|
|
|
|
|
type AuthService struct {
|
|
|
|
userRepo repository.UserRepository
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewAuthService(userRepo repository.UserRepository) *AuthService {
|
|
|
|
return &AuthService{
|
|
|
|
userRepo: userRepo,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Login 用户登录
|
|
|
|
func (s *AuthService) Login(username, password string) (*model.LoginResponse, error) {
|
|
|
|
// 根据用户名查找用户
|
|
|
|
user, err := s.userRepo.GetByUsername(username)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.New("用户名或密码错误")
|
|
|
|
}
|
|
|
|
|
|
|
|
// 验证密码
|
|
|
|
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
|
|
|
|
return nil, errors.New("用户名或密码错误")
|
|
|
|
}
|
|
|
|
|
|
|
|
// 检查用户状态
|
|
|
|
if !user.IsActive {
|
|
|
|
return nil, errors.New("账户已被禁用")
|
|
|
|
}
|
|
|
|
|
|
|
|
// 更新最后登录信息
|
|
|
|
now := time.Now()
|
|
|
|
user.LastLoginAt = &now
|
|
|
|
user.LastLoginIP = "127.0.0.1" // 这里应该从请求中获取真实IP
|
|
|
|
user.LoginCount++
|
|
|
|
|
|
|
|
if err := s.userRepo.Update(user); err != nil {
|
|
|
|
// 登录失败,但不影响登录流程
|
|
|
|
}
|
|
|
|
|
|
|
|
// 生成JWT token
|
|
|
|
token, err := s.generateJWTToken(user)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.New("生成认证令牌失败")
|
|
|
|
}
|
|
|
|
|
|
|
|
// 检查是否需要强制修改密码
|
|
|
|
forceChangePassword := s.checkForceChangePassword(user)
|
|
|
|
|
|
|
|
return &model.LoginResponse{
|
|
|
|
Token: token,
|
|
|
|
User: user,
|
|
|
|
ForceChangePassword: forceChangePassword,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// RefreshToken 刷新JWT token
|
|
|
|
func (s *AuthService) RefreshToken(userID interface{}) (string, error) {
|
|
|
|
// 安全地转换userID
|
|
|
|
var uid uint
|
|
|
|
switch v := userID.(type) {
|
|
|
|
case uint:
|
|
|
|
uid = v
|
|
|
|
case int:
|
|
|
|
if v < 0 {
|
|
|
|
return "", errors.New("无效的用户ID")
|
|
|
|
}
|
|
|
|
uid = uint(v)
|
|
|
|
case int64:
|
|
|
|
if v < 0 {
|
|
|
|
return "", errors.New("无效的用户ID")
|
|
|
|
}
|
|
|
|
uid = uint(v)
|
|
|
|
case float64:
|
|
|
|
if v < 0 || v > float64(^uint(0)) {
|
|
|
|
return "", errors.New("无效的用户ID")
|
|
|
|
}
|
|
|
|
uid = uint(v)
|
|
|
|
case string:
|
|
|
|
if parsed, err := strconv.ParseUint(v, 10, 64); err == nil {
|
|
|
|
uid = uint(parsed)
|
|
|
|
} else {
|
|
|
|
return "", errors.New("无效的用户ID")
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return "", errors.New("无效的用户ID类型")
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取用户信息
|
|
|
|
user, err := s.userRepo.GetByID(uid)
|
|
|
|
if err != nil {
|
|
|
|
return "", errors.New("用户不存在")
|
|
|
|
}
|
|
|
|
|
|
|
|
// 生成新的JWT token
|
|
|
|
return s.generateJWTToken(user)
|
|
|
|
}
|
|
|
|
|
|
|
|
// generateJWTToken 生成JWT token
|
|
|
|
func (s *AuthService) generateJWTToken(user *model.User) (string, error) {
|
|
|
|
// 创建claims
|
|
|
|
claims := jwt.MapClaims{
|
|
|
|
"user_id": user.ID,
|
|
|
|
"username": user.Username,
|
|
|
|
"email": user.Email,
|
|
|
|
"exp": time.Now().Add(time.Hour * 24).Unix(), // 24小时过期
|
|
|
|
"iat": time.Now().Unix(),
|
|
|
|
"iss": "gofaster",
|
|
|
|
}
|
|
|
|
|
|
|
|
// 创建token
|
|
|
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
|
|
|
|
|
|
|
// 签名token
|
|
|
|
tokenString, err := token.SignedString([]byte("your-secret-key"))
|
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("签名token失败: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return tokenString, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// checkForceChangePassword 检查是否需要强制修改密码
|
|
|
|
func (s *AuthService) checkForceChangePassword(user *model.User) bool {
|
|
|
|
return user.ForceChangePassword
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetUserInfo 获取用户信息
|
|
|
|
func (s *AuthService) GetUserInfo(ctx context.Context, userID uint) (*model.UserInfo, error) {
|
|
|
|
// 根据用户ID获取用户信息
|
|
|
|
user, err := s.userRepo.GetByID(userID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.New("用户不存在")
|
|
|
|
}
|
|
|
|
|
|
|
|
// 检查用户状态
|
|
|
|
if !user.IsActive {
|
|
|
|
return nil, errors.New("账户已被禁用")
|
|
|
|
}
|
|
|
|
|
|
|
|
// 转换为UserInfo结构
|
|
|
|
userInfo := &model.UserInfo{
|
|
|
|
ID: user.ID,
|
|
|
|
Username: user.Username,
|
|
|
|
Name: user.Name,
|
|
|
|
Email: user.Email,
|
|
|
|
Phone: user.Phone,
|
|
|
|
Status: user.Status,
|
|
|
|
IsActive: user.IsActive,
|
|
|
|
CreatedAt: user.CreatedAt,
|
|
|
|
UpdatedAt: user.UpdatedAt,
|
|
|
|
LastLoginAt: user.LastLoginAt,
|
|
|
|
LastLoginIP: user.LastLoginIP,
|
|
|
|
LoginCount: user.LoginCount,
|
|
|
|
}
|
|
|
|
|
|
|
|
return userInfo, nil
|
|
|
|
}
|