initial commit: Go version of SMS Receiver with fixed template rendering
- Implemented all core features from Python version - Fixed int64/int type compatibility in template functions - Added login authentication, SMS receiving, statistics, logs - Independent database: sms_receiver_go.db - Fixed frontend display issues for message list and statistics
This commit is contained in:
129
auth/auth.go
Normal file
129
auth/auth.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"sms-receiver-go/config"
|
||||
|
||||
"github.com/gorilla/sessions"
|
||||
)
|
||||
|
||||
var store *sessions.CookieStore
|
||||
|
||||
// SessionKey 会话相关的 key
|
||||
const (
|
||||
SessionKeyLoggedIn = "logged_in"
|
||||
SessionKeyUsername = "username"
|
||||
SessionKeyLoginTime = "login_time"
|
||||
SessionKeyLastActive = "last_activity"
|
||||
)
|
||||
|
||||
// Init 初始化会话存储
|
||||
func Init(secretKey string) {
|
||||
// 支持 hex 和 base64 格式的密钥
|
||||
key := []byte(secretKey)
|
||||
if len(key) == 64 { // hex 格式 32 字节
|
||||
var err error
|
||||
key, err = hex.DecodeString(secretKey)
|
||||
if err != nil {
|
||||
log.Printf("警告: hex 解码失败,使用原始密钥: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
store = sessions.NewCookieStore(key)
|
||||
store.Options = &sessions.Options{
|
||||
Path: "/",
|
||||
MaxAge: 86400 * 7, // 7天
|
||||
HttpOnly: true,
|
||||
// 不设置 SameSite,让浏览器使用默认值(Lax),在同站上下文中工作正常
|
||||
// SameSite: http.SameSiteNoneMode,
|
||||
// Secure: true,
|
||||
}
|
||||
log.Printf("会话存储初始化完成,密钥长度: %d 字节", len(key))
|
||||
}
|
||||
|
||||
// GetStore 获取会话存储
|
||||
func GetStore() *sessions.CookieStore {
|
||||
return store
|
||||
}
|
||||
|
||||
// Login 登录
|
||||
func Login(w http.ResponseWriter, r *http.Request, username string) error {
|
||||
session, err := store.Get(r, "sms-receiver")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
session.Values[SessionKeyLoggedIn] = true
|
||||
session.Values[SessionKeyUsername] = username
|
||||
session.Values[SessionKeyLoginTime] = time.Now().Unix()
|
||||
session.Values[SessionKeyLastActive] = time.Now().Unix()
|
||||
|
||||
return session.Save(r, w)
|
||||
}
|
||||
|
||||
// Logout 登出
|
||||
func Logout(r *http.Request, w http.ResponseWriter) error {
|
||||
session, err := store.Get(r, "sms-receiver")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
session.Values = make(map[interface{}]interface{})
|
||||
session.Save(r, w)
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsLoggedIn 检查是否已登录
|
||||
func IsLoggedIn(r *http.Request) (bool, string) {
|
||||
session, err := store.Get(r, "sms-receiver")
|
||||
if err != nil {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
loggedIn, ok := session.Values[SessionKeyLoggedIn].(bool)
|
||||
if !ok || !loggedIn {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
username, _ := session.Values[SessionKeyUsername].(string)
|
||||
|
||||
// 检查会话是否过期
|
||||
cfg := config.Get()
|
||||
if cfg != nil {
|
||||
lastActive, ok := session.Values[SessionKeyLastActive].(int64)
|
||||
if ok {
|
||||
sessionLifetime := cfg.GetSessionLifetimeDuration()
|
||||
if time.Now().Unix()-lastActive > int64(sessionLifetime.Seconds()) {
|
||||
return false, ""
|
||||
}
|
||||
// 更新最后活跃时间
|
||||
session.Values[SessionKeyLastActive] = time.Now().Unix()
|
||||
}
|
||||
}
|
||||
|
||||
return true, username
|
||||
}
|
||||
|
||||
// CheckLogin 检查登录状态,未登录则跳转到登录页
|
||||
func CheckLogin(w http.ResponseWriter, r *http.Request) (bool, string) {
|
||||
loggedIn, username := IsLoggedIn(r)
|
||||
if !loggedIn {
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return false, ""
|
||||
}
|
||||
return true, username
|
||||
}
|
||||
|
||||
// GetCurrentUser 获取当前用户名
|
||||
func GetCurrentUser(r *http.Request) string {
|
||||
session, err := store.Get(r, "sms-receiver")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
username, _ := session.Values[SessionKeyUsername].(string)
|
||||
return username
|
||||
}
|
||||
Reference in New Issue
Block a user