feat: first working version
This commit is contained in:
parent
a67e208d6e
commit
1029563cb1
11 changed files with 585 additions and 0 deletions
45
cmd/add_user/main.go
Normal file
45
cmd/add_user/main.go
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"linux-auth/internal/db"
|
||||||
|
"linux-auth/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CLI утилита для добавления нового пользователя в базу
|
||||||
|
*
|
||||||
|
* Позволяет добавлять пользователей интерактивно или через аргументы.
|
||||||
|
*/
|
||||||
|
func main() {
|
||||||
|
// ---------- Аргументы ----------
|
||||||
|
username := flag.String("username", "", "Логин нового пользователя")
|
||||||
|
password := flag.String("password", "", "Пароль нового пользователя")
|
||||||
|
dbPath := flag.String("db", "./data/users.db", "Путь к файлу базы данных")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
// ---------- Проверка аргументов ----------
|
||||||
|
if *username == "" || *password == "" {
|
||||||
|
fmt.Println("Использование: go run cmd/add_user/main.go -username USER -password PASS [-db ./data/users.db]")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Инициализация БД ----------
|
||||||
|
err := db.Init(*dbPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Ошибка инициализации БД: %v\n", err)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
// ---------- Создание пользователя ----------
|
||||||
|
hash := utils.HashPassword(*password)
|
||||||
|
err = db.CreateUser(*username, hash)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Не удалось создать пользователя %s: %v\n", *username, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Пользователь %s успешно добавлен.\n", *username)
|
||||||
|
}
|
||||||
88
cmd/authapp/main.go
Normal file
88
cmd/authapp/main.go
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"linux-auth/internal/auth"
|
||||||
|
"linux-auth/internal/config"
|
||||||
|
"linux-auth/internal/db"
|
||||||
|
"linux-auth/internal/ui"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Точка входа в приложение аутентификации
|
||||||
|
*
|
||||||
|
* Программа загружает конфигурацию, инициализирует БД
|
||||||
|
* и запускает цикл аутентификации пользователя.
|
||||||
|
*/
|
||||||
|
func main() {
|
||||||
|
// ---------- Работа с аргументами ----------
|
||||||
|
configPath := flag.String(
|
||||||
|
"config",
|
||||||
|
"configs/config.toml",
|
||||||
|
"Путь к конфигурационному файлу",
|
||||||
|
)
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
// ---------- Загрузка конфигурации ----------
|
||||||
|
cfg, err := config.Load(*configPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Ошибка загрузки конфигурации: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.App.Name != "" {
|
||||||
|
fmt.Println("=== ", cfg.App.Name, " ===")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Инициализация БД ----------
|
||||||
|
err = db.Init(cfg.Database.Path)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Ошибка инициализации БД: %v\n", err)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
// ---------- Основной цикл аутентификации ----------
|
||||||
|
attempts := 0
|
||||||
|
|
||||||
|
for {
|
||||||
|
// Проверка лимита попыток
|
||||||
|
if attempts >= cfg.App.MaxLoginAttempts {
|
||||||
|
fmt.Println("Превышено количество попыток входа.")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ввод логина и пароля
|
||||||
|
username, password, err := ui.ReadCredentials()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Ошибка ввода данных.")
|
||||||
|
attempts++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверка аутентификации
|
||||||
|
ok, err := auth.Authenticate(username, password)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Ошибка аутентификации: %v\n", err)
|
||||||
|
attempts++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
fmt.Printf("Доступ разрешён. Добро пожаловать, %s!\n", username)
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
fmt.Println("Неверный логин или пароль.")
|
||||||
|
attempts++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Предложение очистки формы (логическое)
|
||||||
|
if ui.AskReset() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Работа приложения завершена.")
|
||||||
|
}
|
||||||
39
cmd/init_users/main.go
Normal file
39
cmd/init_users/main.go
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"linux-auth/internal/db"
|
||||||
|
"linux-auth/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Путь к файлу базы данных
|
||||||
|
dbPath := "./data/users.db"
|
||||||
|
|
||||||
|
// Инициализация БД
|
||||||
|
err := db.Init(dbPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Ошибка инициализации БД: %v\n", err)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
// Создаём пользователей
|
||||||
|
users := map[string]string{
|
||||||
|
"admin": "admin123",
|
||||||
|
"user1": "password1",
|
||||||
|
}
|
||||||
|
|
||||||
|
for username, password := range users {
|
||||||
|
hash := utils.HashPassword(password)
|
||||||
|
err := db.CreateUser(username, hash)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Не удалось создать пользователя %s: %v\n", username, err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Пользователь %s успешно создан.\n", username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Инициализация пользователей завершена.")
|
||||||
|
}
|
||||||
21
configs/config.toml
Normal file
21
configs/config.toml
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
[app]
|
||||||
|
# Название приложения
|
||||||
|
name = "AuthApp"
|
||||||
|
# Максимальное количество попыток входа
|
||||||
|
max_login_attempts = 3
|
||||||
|
# Время блокировки пользователя (сек)
|
||||||
|
lock_timeout_sec = 300
|
||||||
|
|
||||||
|
[database]
|
||||||
|
# Тип базы данных (для будущей расширяемости)
|
||||||
|
type = "sqlite"
|
||||||
|
# Путь к файлу базы данных SQLite
|
||||||
|
path = "./data/users.db"
|
||||||
|
|
||||||
|
[security]
|
||||||
|
# Тип хеширования пароля
|
||||||
|
password_hash = "sha256"
|
||||||
|
|
||||||
|
[ui]
|
||||||
|
# Показать приветственное сообщение при старте
|
||||||
|
show_welcome = true
|
||||||
11
go.mod
Normal file
11
go.mod
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
module linux-auth
|
||||||
|
|
||||||
|
go 1.25.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.33
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.4
|
||||||
|
golang.org/x/term v0.39.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require golang.org/x/sys v0.40.0 // indirect
|
||||||
8
go.sum
Normal file
8
go.sum
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.33 h1:A5blZ5ulQo2AtayQ9/limgHEkFreKj1Dv226a1K73s0=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.33/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||||
|
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||||
|
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
|
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
|
||||||
|
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
|
||||||
54
internal/auth/auth.go
Normal file
54
internal/auth/auth.go
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"linux-auth/internal/db"
|
||||||
|
"linux-auth/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Проверка аутентификации пользователя
|
||||||
|
*
|
||||||
|
* Сравнивает введённый пароль с хешем из БД.
|
||||||
|
* Учитывает блокировку пользователя и количество неудачных попыток.
|
||||||
|
*
|
||||||
|
* @param username Логин пользователя
|
||||||
|
* @param password Введённый пароль
|
||||||
|
* @return true если доступ разрешён, false если логин/пароль неверны
|
||||||
|
* @return ошибка если произошла системная ошибка (например, БД)
|
||||||
|
*/
|
||||||
|
func Authenticate(username, password string) (bool, error) {
|
||||||
|
user, err := db.GetUser(username)
|
||||||
|
if err != nil {
|
||||||
|
// Пользователь не найден
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверка блокировки
|
||||||
|
if user.Locked {
|
||||||
|
return false, errors.New("пользователь заблокирован")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверка пароля
|
||||||
|
if !utils.CheckPassword(password, user.PasswordHash) {
|
||||||
|
// Инкрементируем счётчик неудачных попыток
|
||||||
|
err := db.IncrementFail(username)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если достигнут максимум — блокируем
|
||||||
|
const MaxAttempts = 3 // Можно передавать через config.toml
|
||||||
|
user.FailedAttempts++
|
||||||
|
if user.FailedAttempts >= MaxAttempts {
|
||||||
|
_ = db.LockUser(username)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Успешный вход — сбрасываем счётчик неудачных попыток
|
||||||
|
_ = db.ResetFails(username)
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
53
internal/config/config.go
Normal file
53
internal/config/config.go
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/pelletier/go-toml/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Структура конфигурации приложения
|
||||||
|
*/
|
||||||
|
type Config struct {
|
||||||
|
App struct {
|
||||||
|
Name string `toml:"name"`
|
||||||
|
MaxLoginAttempts int `toml:"max_login_attempts"`
|
||||||
|
LockTimeoutSec int `toml:"lock_timeout_sec"`
|
||||||
|
} `toml:"app"`
|
||||||
|
|
||||||
|
Database struct {
|
||||||
|
Type string `toml:"type"`
|
||||||
|
Path string `toml:"path"`
|
||||||
|
} `toml:"database"`
|
||||||
|
|
||||||
|
Security struct {
|
||||||
|
PasswordHash string `toml:"password_hash"`
|
||||||
|
} `toml:"security"`
|
||||||
|
|
||||||
|
UI struct {
|
||||||
|
ShowWelcome bool `toml:"show_welcome"`
|
||||||
|
} `toml:"ui"`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Загрузка конфигурации из TOML файла
|
||||||
|
*
|
||||||
|
* @param path путь к файлу конфигурации
|
||||||
|
* @return cfg указатель на структуру Config
|
||||||
|
* @return error ошибка при загрузке
|
||||||
|
*/
|
||||||
|
func Load(path string) (*Config, error) {
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfg Config
|
||||||
|
err = toml.Unmarshal(data, &cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &cfg, nil
|
||||||
|
}
|
||||||
170
internal/db/sqlite.go
Normal file
170
internal/db/sqlite.go
Normal file
|
|
@ -0,0 +1,170 @@
|
||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Структура пользователя
|
||||||
|
*/
|
||||||
|
type User struct {
|
||||||
|
ID int
|
||||||
|
Username string
|
||||||
|
PasswordHash string
|
||||||
|
FailedAttempts int
|
||||||
|
Locked bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var database *sql.DB
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Инициализация соединения с SQLite БД
|
||||||
|
* @param path Путь к файлу базы данных
|
||||||
|
* @return ошибка при неудаче
|
||||||
|
*/
|
||||||
|
func Init(path string) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
database, err = sql.Open("sqlite3", path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверка соединения
|
||||||
|
if err = database.Ping(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return createTables()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Закрытие соединения с БД
|
||||||
|
*/
|
||||||
|
func Close() {
|
||||||
|
if database != nil {
|
||||||
|
_ = database.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Создание таблиц при первом запуске
|
||||||
|
*/
|
||||||
|
func createTables() error {
|
||||||
|
query := `
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
username TEXT UNIQUE NOT NULL,
|
||||||
|
password_hash TEXT NOT NULL,
|
||||||
|
failed_attempts INTEGER DEFAULT 0,
|
||||||
|
locked INTEGER DEFAULT 0
|
||||||
|
);
|
||||||
|
`
|
||||||
|
|
||||||
|
_, err := database.Exec(query)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Получить пользователя по имени
|
||||||
|
* @param username Логин пользователя
|
||||||
|
* @return структура User или ошибка
|
||||||
|
*/
|
||||||
|
func GetUser(username string) (*User, error) {
|
||||||
|
query := `
|
||||||
|
SELECT id, username, password_hash, failed_attempts, locked
|
||||||
|
FROM users
|
||||||
|
WHERE username = ?;
|
||||||
|
`
|
||||||
|
|
||||||
|
row := database.QueryRow(query, username)
|
||||||
|
|
||||||
|
var user User
|
||||||
|
var locked int
|
||||||
|
|
||||||
|
err := row.Scan(
|
||||||
|
&user.ID,
|
||||||
|
&user.Username,
|
||||||
|
&user.PasswordHash,
|
||||||
|
&user.FailedAttempts,
|
||||||
|
&locked,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, errors.New("пользователь не найден")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
user.Locked = locked != 0
|
||||||
|
return &user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Увеличить счётчик неудачных попыток входа
|
||||||
|
* @param username Логин пользователя
|
||||||
|
*/
|
||||||
|
func IncrementFail(username string) error {
|
||||||
|
query := `
|
||||||
|
UPDATE users
|
||||||
|
SET failed_attempts = failed_attempts + 1
|
||||||
|
WHERE username = ?;
|
||||||
|
`
|
||||||
|
|
||||||
|
_, err := database.Exec(query, username)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Сбросить счётчик неудачных попыток
|
||||||
|
* @param username Логин пользователя
|
||||||
|
*/
|
||||||
|
func ResetFails(username string) error {
|
||||||
|
query := `
|
||||||
|
UPDATE users
|
||||||
|
SET failed_attempts = 0
|
||||||
|
WHERE username = ?;
|
||||||
|
`
|
||||||
|
|
||||||
|
_, err := database.Exec(query, username)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Заблокировать пользователя
|
||||||
|
* @param username Логин пользователя
|
||||||
|
*/
|
||||||
|
func LockUser(username string) error {
|
||||||
|
query := `
|
||||||
|
UPDATE users
|
||||||
|
SET locked = 1
|
||||||
|
WHERE username = ?;
|
||||||
|
`
|
||||||
|
|
||||||
|
_, err := database.Exec(query)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Добавить нового пользователя (для инициализации)
|
||||||
|
* @param username Логин
|
||||||
|
* @param passwordHash Хеш пароля
|
||||||
|
*/
|
||||||
|
func CreateUser(username, passwordHash string) error {
|
||||||
|
query := `
|
||||||
|
INSERT INTO users (username, password_hash)
|
||||||
|
VALUES (?, ?);
|
||||||
|
`
|
||||||
|
|
||||||
|
_, err := database.Exec(query, username, passwordHash)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("не удалось создать пользователя: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
70
internal/ui/console.go
Normal file
70
internal/ui/console.go
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/term"
|
||||||
|
)
|
||||||
|
|
||||||
|
var reader = bufio.NewReader(os.Stdin)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Считывание логина и пароля с консоли
|
||||||
|
*
|
||||||
|
* Логин вводится обычным текстом, пароль — с маской.
|
||||||
|
*
|
||||||
|
* @return login введённый логин
|
||||||
|
* @return password введённый пароль
|
||||||
|
* @return err ошибка при вводе
|
||||||
|
*/
|
||||||
|
func ReadCredentials() (login string, password string, err error) {
|
||||||
|
// Ввод логина
|
||||||
|
fmt.Print("Логин: ")
|
||||||
|
login, err = reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
login = strings.TrimSpace(login)
|
||||||
|
|
||||||
|
// Ввод пароля с маской
|
||||||
|
fmt.Print("Пароль: ")
|
||||||
|
bytePassword, err := term.ReadPassword(int(syscall.Stdin))
|
||||||
|
fmt.Println()
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
password = strings.TrimSpace(string(bytePassword))
|
||||||
|
|
||||||
|
return login, password, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Предложить пользователю очистку формы
|
||||||
|
*
|
||||||
|
* Пользователь может ввести "y" или "n".
|
||||||
|
*
|
||||||
|
* @return true если пользователь выбрал сброс
|
||||||
|
*/
|
||||||
|
func AskReset() bool {
|
||||||
|
for {
|
||||||
|
fmt.Print("Очистить форму и попробовать снова? (y/n): ")
|
||||||
|
resp, err := reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
resp = strings.ToLower(strings.TrimSpace(resp))
|
||||||
|
|
||||||
|
if resp == "y" || resp == "yes" {
|
||||||
|
return true
|
||||||
|
} else if resp == "n" || resp == "no" {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
fmt.Println("Введите y или n.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
internal/utils/hash.go
Normal file
26
internal/utils/hash.go
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Вычислить SHA-256 хеш пароля
|
||||||
|
* @param password Строка с паролем
|
||||||
|
* @return Хеш в виде строки HEX
|
||||||
|
*/
|
||||||
|
func HashPassword(password string) string {
|
||||||
|
hash := sha256.Sum256([]byte(password))
|
||||||
|
return hex.EncodeToString(hash[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Проверить совпадение пароля и хеша
|
||||||
|
* @param password Введённый пароль
|
||||||
|
* @param hash Хеш пароля из БД
|
||||||
|
* @return true если совпадает
|
||||||
|
*/
|
||||||
|
func CheckPassword(password, hash string) bool {
|
||||||
|
return HashPassword(password) == hash
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue