2026-02-12 13:48:35 +08:00
|
|
|
|
package routers
|
2025-04-01 17:59:10 +08:00
|
|
|
|
|
|
|
|
|
|
import (
|
2025-04-15 16:47:00 +08:00
|
|
|
|
"fmt"
|
2025-04-09 16:56:05 +08:00
|
|
|
|
"go_blog/controllers"
|
2025-07-12 15:56:36 +08:00
|
|
|
|
"go_blog/controllers/admin"
|
2025-04-01 17:59:10 +08:00
|
|
|
|
"net/http"
|
2025-05-22 13:56:57 +08:00
|
|
|
|
"time"
|
2025-04-01 17:59:10 +08:00
|
|
|
|
|
2025-06-13 08:59:01 +08:00
|
|
|
|
"github.com/gin-contrib/sessions"
|
2025-04-01 17:59:10 +08:00
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2026-02-12 13:48:35 +08:00
|
|
|
|
// CheckAdminAuth 后台认证中间件(处理页面重定向)
|
2025-06-09 17:59:19 +08:00
|
|
|
|
func CheckAdminAuth() gin.HandlerFunc {
|
2025-06-18 18:34:08 +08:00
|
|
|
|
return func(c *gin.Context) {
|
|
|
|
|
|
currentPath := c.Request.URL.Path
|
|
|
|
|
|
session := sessions.Default(c) // 获取当前请求的Session
|
|
|
|
|
|
userID := session.Get("user_id") // 从Session中获取用户ID
|
|
|
|
|
|
loggedIn := userID != nil && userID != ""
|
|
|
|
|
|
|
|
|
|
|
|
// 已登录状态访问登录/注册页:重定向到后台首页
|
|
|
|
|
|
if (currentPath == "/admin/login" || currentPath == "/admin/register") && loggedIn {
|
|
|
|
|
|
c.Redirect(http.StatusFound, "/admin/index")
|
|
|
|
|
|
c.Abort()
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 未登录状态访问非登录/注册页:重定向到登录页
|
|
|
|
|
|
if (currentPath != "/admin/login" && currentPath != "/admin/register") && !loggedIn {
|
|
|
|
|
|
c.Redirect(http.StatusFound, "/admin/login")
|
|
|
|
|
|
c.Abort()
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c.Next()
|
|
|
|
|
|
}
|
2025-06-13 08:59:01 +08:00
|
|
|
|
}
|
2025-06-09 17:59:19 +08:00
|
|
|
|
|
2026-02-12 13:48:35 +08:00
|
|
|
|
// SessionAuthRequired 基于Session的认证中间件
|
2025-06-13 08:59:01 +08:00
|
|
|
|
func SessionAuthRequired() gin.HandlerFunc {
|
|
|
|
|
|
return func(c *gin.Context) {
|
|
|
|
|
|
session := sessions.Default(c)
|
|
|
|
|
|
userID := session.Get("user_id")
|
|
|
|
|
|
if userID == nil {
|
|
|
|
|
|
// 未登录,重定向到登录页
|
2025-06-09 17:59:19 +08:00
|
|
|
|
c.Redirect(http.StatusFound, "/admin/login")
|
|
|
|
|
|
c.Abort()
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2025-06-13 08:59:01 +08:00
|
|
|
|
// 可选:根据userID查询用户信息并注入上下文
|
|
|
|
|
|
// user, err := models.GetAccountByID(userID.(uint))
|
|
|
|
|
|
// if err != nil { ... }
|
|
|
|
|
|
// c.Set("user", user)
|
2025-06-09 17:59:19 +08:00
|
|
|
|
c.Next()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-01 17:59:10 +08:00
|
|
|
|
func RegisterRoutes(r *gin.Engine) {
|
2026-02-12 13:48:35 +08:00
|
|
|
|
// WebSocket 和 SSE 路由
|
2025-04-15 16:47:00 +08:00
|
|
|
|
r.GET("/events", esSSE)
|
|
|
|
|
|
r.GET("/ws", controllers.WebSocketHandler)
|
2026-02-12 13:48:35 +08:00
|
|
|
|
|
|
|
|
|
|
// 内容相关路由
|
2025-04-15 16:47:00 +08:00
|
|
|
|
r.POST("/content", controllers.CreateContentHandler)
|
2026-02-12 13:48:35 +08:00
|
|
|
|
r.GET("/page", controllers.PageList)
|
|
|
|
|
|
r.GET("/createcontent", controllers.CreateContentPage)
|
|
|
|
|
|
|
|
|
|
|
|
// 前端路由(动态主题)
|
2025-04-09 16:56:05 +08:00
|
|
|
|
r.GET("/", controllers.Home)
|
|
|
|
|
|
r.GET("/post/:id", controllers.ShowPost)
|
2025-04-01 17:59:10 +08:00
|
|
|
|
|
2025-07-12 15:56:36 +08:00
|
|
|
|
adminGroup := r.Group("/admin")
|
|
|
|
|
|
adminGroup.Use(CheckAdminAuth())
|
2025-05-27 19:01:05 +08:00
|
|
|
|
{
|
2025-06-09 17:59:19 +08:00
|
|
|
|
// 无需认证的公开路由(登录/注册)
|
2025-06-13 08:59:01 +08:00
|
|
|
|
// 新增:处理 /admin 根路径跳转
|
2025-07-12 15:56:36 +08:00
|
|
|
|
adminGroup.GET("/", func(c *gin.Context) {
|
|
|
|
|
|
|
2025-06-13 08:59:01 +08:00
|
|
|
|
// 由于 CheckAdminAuth 中间件已处理未登录场景,此处用户必定已登录
|
|
|
|
|
|
c.Redirect(http.StatusFound, "/admin/index")
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2025-07-12 15:56:36 +08:00
|
|
|
|
adminGroup.GET("/login", admin.ShowLoginPage)
|
|
|
|
|
|
adminGroup.GET("/register", admin.ShowRegisterPage)
|
|
|
|
|
|
adminGroup.POST("/login", admin.UsersLoginHandler)
|
|
|
|
|
|
adminGroup.POST("/register", admin.UsersRegisterHandler)
|
2025-06-09 17:59:19 +08:00
|
|
|
|
|
2025-06-13 08:59:01 +08:00
|
|
|
|
// 需要认证的路由组
|
2025-07-12 15:56:36 +08:00
|
|
|
|
authAdmin := adminGroup.Group("", SessionAuthRequired())
|
2025-06-09 17:59:19 +08:00
|
|
|
|
{
|
2025-07-12 15:56:36 +08:00
|
|
|
|
authAdmin.GET("/index", admin.ShowAdminIndexPage)
|
|
|
|
|
|
authAdmin.GET("/themes", admin.ListThemes)
|
|
|
|
|
|
authAdmin.POST("/themes/switch", admin.SwitchTheme)
|
|
|
|
|
|
authAdmin.POST("/setpwd", admin.UsersSetPwdHandler)
|
|
|
|
|
|
authAdmin.GET("/logout", admin.UsersLogoutHandler) // 添加退出路由
|
2025-06-09 17:59:19 +08:00
|
|
|
|
}
|
2025-05-27 19:01:05 +08:00
|
|
|
|
}
|
2025-04-01 17:59:10 +08:00
|
|
|
|
|
|
|
|
|
|
// Static files for themes
|
|
|
|
|
|
r.StaticFS("/themes", http.Dir("web/themes"))
|
|
|
|
|
|
}
|
2025-04-15 16:47:00 +08:00
|
|
|
|
|
|
|
|
|
|
func esSSE(c *gin.Context) {
|
|
|
|
|
|
w := c.Writer
|
|
|
|
|
|
|
|
|
|
|
|
w.Header().Set("Content-Type", "text/event-stream")
|
|
|
|
|
|
w.Header().Set("Cache-Control", "no-cache")
|
|
|
|
|
|
w.Header().Set("Connection", "keep-alive")
|
|
|
|
|
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
|
|
|
|
|
|
2026-02-12 13:48:35 +08:00
|
|
|
|
flusher, ok := w.(http.Flusher)
|
2025-04-15 16:47:00 +08:00
|
|
|
|
if !ok {
|
2026-02-12 13:48:35 +08:00
|
|
|
|
c.String(http.StatusInternalServerError, "server not support SSE")
|
|
|
|
|
|
return
|
2025-04-15 16:47:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-22 13:56:57 +08:00
|
|
|
|
for {
|
|
|
|
|
|
fmt.Fprintf(w, "data: %s\n\n", time.Now().Format(time.Stamp))
|
2026-02-12 13:48:35 +08:00
|
|
|
|
flusher.Flush()
|
2025-05-22 13:56:57 +08:00
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
|
|
}
|
2025-04-15 16:47:00 +08:00
|
|
|
|
}
|