package auth import ( "errors" "time" "github.com/golang-jwt/jwt/v5" "golang.org/x/crypto/bcrypt" ) // HashPassword bcrypt 哈希 func HashPassword(password string) (string, error) { b, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return "", err } return string(b), nil } // VerifyPassword 校验密码 func VerifyPassword(password, hashed string) bool { return bcrypt.CompareHashAndPassword([]byte(hashed), []byte(password)) == nil } // CreateToken 签发 JWT(HS256),payload 对齐 Python:sub/role/iat/exp func CreateToken(username, role, secret string, expireMin int) (string, error) { now := time.Now() claims := jwt.MapClaims{ "sub": username, "role": role, "iat": now.Unix(), "exp": now.Add(time.Duration(expireMin) * time.Minute).Unix(), } return jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString([]byte(secret)) } // SignClaims 通用 JWT 签发(考试会话等复用) func SignClaims(claims jwt.MapClaims, secret string) (string, error) { return jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString([]byte(secret)) } // ParseToken 校验 JWT,返回 claims。失败返回 error。 func ParseToken(tokenStr, secret string) (jwt.MapClaims, error) { token, err := jwt.Parse(tokenStr, func(t *jwt.Token) (any, error) { if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok { return nil, jwt.ErrSignatureInvalid } return []byte(secret), nil }) if err != nil { return nil, err } claims, ok := token.Claims.(jwt.MapClaims) if !ok || !token.Valid { return nil, errors.New("invalid token claims") } return claims, nil }