feat: 云笔记增强 - 安全加固 + 回收站/版本历史/分享/批量导出 + 前端优化
- 安全: 认证改随机token会话(弃固定cookie), 笔记密码SHA256升级为bcrypt(自动迁移), 堵住GET /api/notes/:id泄露带密码笔记, CORS收紧+SameSite防CSRF, 上传图片内容嗅探 - 回收站: 软删除(deleted_at), 列表/恢复/彻底删除/清空, 目录子树连删连恢复 - 版本历史: note_versions表存快照, 每次保存自动留档, 支持查看/回滚 - 分享: 生成随机token分享链接, 支持过期时间, 公开阅读页share.html - 批量导出: 全部笔记打包zip(按目录结构+front matter) - 前端: 深色模式, Mermaid图表, 待办清单checkbox, 字数统计; 后台新增回收站/历史/分享面板和批量导出按钮 - 新增deploy/note-manager.service systemd单元与smoke_test.py
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"note-manager/config"
|
||||
"note-manager/middleware"
|
||||
"note-manager/service"
|
||||
)
|
||||
|
||||
@@ -19,7 +20,7 @@ func NewAdminHandler(noteSvc *service.NoteService, cfg *config.Config) *AdminHan
|
||||
return &AdminHandler{noteSvc: noteSvc, config: cfg}
|
||||
}
|
||||
|
||||
// Login 登录页面
|
||||
// LoginPage 登录页面
|
||||
func (h *AdminHandler) LoginPage(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "login.html", gin.H{
|
||||
"title": "后台管理登录",
|
||||
@@ -30,8 +31,11 @@ func (h *AdminHandler) LoginPage(c *gin.Context) {
|
||||
func (h *AdminHandler) Login(c *gin.Context) {
|
||||
password := c.PostForm("password")
|
||||
if password == h.config.AdminPass {
|
||||
// 设置 cookie,有效期 7 天
|
||||
c.SetCookie("admin_token", "authenticated", 7*24*3600, "/", "", false, true)
|
||||
// 生成随机会话 token
|
||||
token, _ := middleware.NewSessionToken()
|
||||
// 通过环境变量判断是否启用 HTTPS(生产建议配置)
|
||||
secure := c.Request.TLS != nil
|
||||
middleware.SetAuthCookie(c, token, secure)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"message": "登录成功",
|
||||
@@ -46,7 +50,8 @@ func (h *AdminHandler) Login(c *gin.Context) {
|
||||
|
||||
// Logout 登出
|
||||
func (h *AdminHandler) Logout(c *gin.Context) {
|
||||
c.SetCookie("admin_token", "", -1, "/", "", false, true)
|
||||
middleware.RevokeSession(middleware.GetAuthToken(c))
|
||||
middleware.ClearAuthCookie(c)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"message": "已退出登录",
|
||||
@@ -55,8 +60,8 @@ func (h *AdminHandler) Logout(c *gin.Context) {
|
||||
|
||||
// CheckAuth 检查是否已登录
|
||||
func (h *AdminHandler) CheckAuth(c *gin.Context) {
|
||||
token, err := c.Cookie("admin_token")
|
||||
if err == nil && token == "authenticated" {
|
||||
token := middleware.GetAuthToken(c)
|
||||
if middleware.IsValidSession(token) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"message": "已登录",
|
||||
@@ -77,8 +82,8 @@ func (h *AdminHandler) CheckAuth(c *gin.Context) {
|
||||
|
||||
// IndexPage 后台管理首页
|
||||
func (h *AdminHandler) IndexPage(c *gin.Context) {
|
||||
token, err := c.Cookie("admin_token")
|
||||
if err != nil || token != "authenticated" {
|
||||
token := middleware.GetAuthToken(c)
|
||||
if !middleware.IsValidSession(token) {
|
||||
c.Redirect(http.StatusFound, "/admin/login")
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user