Done
This commit is contained in:
0
backend/config/.env
Normal file
0
backend/config/.env
Normal file
11
backend/go.mod
Normal file
11
backend/go.mod
Normal file
@@ -0,0 +1,11 @@
|
||||
module firewall-system
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/gorilla/sessions v1.2.1
|
||||
golang.org/x/crypto v0.9.0
|
||||
golang.org/x/time v0.3.0
|
||||
modernc.org/sqlite v1.21.1
|
||||
)
|
10
backend/go.sum
Normal file
10
backend/go.sum
Normal file
@@ -0,0 +1,10 @@
|
||||
github.com/gorilla/mux v1.8.0 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/sessions v1.2.1 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbM=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:8KCfur6+4TmpsXA+g09ya2YtYYsFw5D7sE4fLH1NfK4=
|
||||
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
modernc.org/sqlite v1.21.1 h1:6JQQqG9n7z7ZtL0vZ+5nZ5y5y5Z5y5Z5y5Z5y5Z5y5Z5=
|
||||
modernc.org/sqlite v1.21.1/go.mod h1:5ZQP2yCQ6z+X5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5=
|
54
backend/main.go
Normal file
54
backend/main.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/sessions"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
var (
|
||||
db *sql.DB
|
||||
store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_SECRET")))
|
||||
)
|
||||
|
||||
func main() {
|
||||
initDB()
|
||||
defer db.Close()
|
||||
|
||||
r := mux.NewRouter()
|
||||
r.Use(middleware.CORS, middleware.RateLimit, middleware.AuditLog)
|
||||
|
||||
// 公共路由
|
||||
r.HandleFunc("/api/register", registerHandler).Methods("POST")
|
||||
r.HandleFunc("/api/login", loginHandler).Methods("POST")
|
||||
|
||||
// 用户路由
|
||||
userRouter := r.PathPrefix("/api/user").Subrouter()
|
||||
userRouter.Use(middleware.Auth)
|
||||
userRouter.HandleFunc("/request", submitIPRequestHandler).Methods("POST")
|
||||
|
||||
// 管理路由
|
||||
adminRouter := r.PathPrefix("/api/admin").Subrouter()
|
||||
adminRouter.Use(middleware.AdminAuth)
|
||||
adminRouter.HandleFunc("/approve", approveRequestHandler).Methods("POST")
|
||||
|
||||
log.Println("Server started on :8080")
|
||||
log.Fatal(http.ListenAndServe(":8080", r))
|
||||
}
|
||||
|
||||
func initDB() {
|
||||
var err error
|
||||
db, err = sql.Open("sqlite", "db/firewall.db")
|
||||
if err != nil {
|
||||
log.Fatal("Failed to open database:", err)
|
||||
}
|
||||
}
|
21
backend/middleware/audit.go
Normal file
21
backend/middleware/audit.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 审计日志中间件
|
||||
func AuditLog(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
next.ServeHTTP(w, r)
|
||||
log.Printf(
|
||||
"Method=%s Path=%s Duration=%s",
|
||||
r.Method,
|
||||
r.URL.Path,
|
||||
time.Since(start),
|
||||
)
|
||||
})
|
||||
}
|
32
backend/middleware/auth.go
Normal file
32
backend/middleware/auth.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"github.com/gorilla/sessions"
|
||||
)
|
||||
|
||||
var store = sessions.NewCookieStore([]byte("your-secret-key"))
|
||||
|
||||
// 用户认证中间件
|
||||
func Auth(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
session, _ := store.Get(r, "session")
|
||||
if auth, ok := session.Values["authenticated"].(bool); !ok || !auth {
|
||||
http.Error(w, "未授权访问", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// 管理员认证中间件
|
||||
func AdminAuth(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
session, _ := store.Get(r, "session")
|
||||
if role, ok := session.Values["role"].(string); !ok || role != "admin" {
|
||||
http.Error(w, "需要管理员权限", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
19
backend/middleware/rate_limit.go
Normal file
19
backend/middleware/rate_limit.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
var limiter = rate.NewLimiter(rate.Every(1*time.Minute), 5)
|
||||
|
||||
// 请求频率限制中间件
|
||||
func RateLimit(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if !limiter.Allow() {
|
||||
http.Error(w, "请求过于频繁", http.StatusTooManyRequests)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
17
backend/scripts/init_admin.sh
Normal file
17
backend/scripts/init_admin.sh
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
DB_PATH="db/firewall.db"
|
||||
ADMIN_USER="superadmin"
|
||||
ADMIN_PASS="ChangeThisPassword123!"
|
||||
|
||||
# 生成密码哈希
|
||||
HASH=$(echo -n "$ADMIN_PASS" | bcrypt-cli -c 12)
|
||||
|
||||
sqlite3 "$DB_PATH" <<EOF
|
||||
INSERT INTO users (username, password_hash, role)
|
||||
VALUES ('$ADMIN_USER', '$HASH', 'superadmin');
|
||||
EOF
|
||||
|
||||
echo "管理员账户初始化完成"
|
||||
echo "用户名: $ADMIN_USER"
|
||||
echo "密码: $ADMIN_PASS"
|
28
backend/scripts/init_db.sql
Normal file
28
backend/scripts/init_db.sql
Normal file
@@ -0,0 +1,28 @@
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT UNIQUE NOT NULL,
|
||||
password_hash TEXT NOT NULL,
|
||||
role TEXT NOT NULL DEFAULT 'user',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ip_requests (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL,
|
||||
ip TEXT NOT NULL,
|
||||
status TEXT DEFAULT 'pending',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY(user_id) REFERENCES users(id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS audit_logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER,
|
||||
action TEXT,
|
||||
ip TEXT,
|
||||
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
COMMIT;
|
Reference in New Issue
Block a user