可靠性: PostgreSQL 无 Redis 时 session 不再误用 MySQL 存储

This commit is contained in:
tamakyi
2026-11-05 12:16:46 +08:00
parent 937e688cfa
commit 7636456d4e
2 changed files with 76 additions and 32 deletions
+24 -32
View File
@@ -48,6 +48,29 @@ import (
"github.com/tamakyi/TamaBox/templates"
)
func sessionOptions() session.Options {
options := session.Options{
Initer: session.MemoryIniter(),
Cookie: session.CookieOptions{
HTTPOnly: true,
SameSite: http.SameSiteLaxMode,
Secure: strings.HasPrefix(conf.App.ExternalURL, "https"),
},
}
if conf.Database.DSN != "" && (conf.Database.Type == "" || conf.Database.Type == "mysql") {
options.Initer = mysql.Initer()
options.Config = mysql.Config{DSN: conf.Database.DSN, Lifetime: 7 * 24 * time.Hour}
}
if conf.Redis.Addr != "" {
options.Initer = sessionRedis.Initer()
options.Config = sessionRedis.Config{
Options: &sessionRedis.Options{Addr: conf.Redis.Addr, Password: conf.Redis.Password, DB: 1},
Lifetime: 7 * 24 * time.Hour,
}
}
return options
}
// indexNowKeyPattern 限制 IndexNow 密钥文件名的合法形态:32 位小写十六进制 + ".txt"。
// 用于防止把路由参数直接拼进 embed FS 路径时发生路径穿越(如 "../robots.txt")。
var indexNowKeyPattern = regexp.MustCompile(`^[0-9a-f]{32}\.txt$`)
@@ -243,38 +266,7 @@ func New() *flamego.Flame {
gob.Register(time.Time{})
gob.Register(context.Flash{})
gob.Register(captcha.StoredAnswer{})
var sessionStorage interface{}
initer := session.MemoryIniter()
if conf.Database.DSN != "" {
initer = mysql.Initer()
sessionStorage = mysql.Config{
DSN: conf.Database.DSN,
Lifetime: 7 * 24 * time.Hour,
}
}
if conf.Redis.Addr != "" {
initer = sessionRedis.Initer()
sessionStorage = sessionRedis.Config{
Options: &sessionRedis.Options{
Addr: conf.Redis.Addr,
Password: conf.Redis.Password,
DB: 1,
},
Lifetime: 7 * 24 * time.Hour,
}
}
sessioner := session.Sessioner(session.Options{
Initer: initer,
Config: sessionStorage,
// 显式声明 cookie 安全属性:HTTPOnly 防 XSS 窃取会话;SameSite=Lax 阻断跨站表单
// POST;Secure 仅在 https 对外服务时下发,避免 http 本地开发下 cookie 不生效
// (缺失 Secure 时,HSTS 尚未落地的首次访问可被 MITM 诱导明文请求窃取会话)。
Cookie: session.CookieOptions{
HTTPOnly: true,
SameSite: http.SameSiteLaxMode,
Secure: strings.HasPrefix(conf.App.ExternalURL, "https"),
},
})
sessioner := session.Sessioner(sessionOptions())
// 安全响应头必须注册在静态资源之前:flamego.Static 命中后会终结请求链,
// 放在它后面等于静态资源拿不到 nosniff / HSTS。