Golang中Cookie重定向问题的解决方法

Golang中Cookie重定向问题的解决方法 大家好,我似乎无法解决这个问题。我有一个Golang网站,连接正常并能创建会话,但我想使用Cookie来重定向到预订页面。希望有人能帮助我,我似乎无法让重定向正常工作。我需要它能够检查用户、创建ID和会话,然后验证是否一切正常,接着创建Cookie并从登录页面重定向到预订页面。

GitHub: GitHub - KSCHNAPPIEN/golang-web

package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"github.com/gorilla/sessions"
	_ "github.com/gorilla/sessions"
)

type DatabaseConfig struct {
	Username string `json:"user"`
	Password string `json:"password"`
	Host     string `json:"host"`
	Port     int    `json:"port"`
	Database string `json:"dbname"`
}

var id bool
var dbc string
var userID int
var store = sessions.NewCookieStore([]byte("logging succes secrect key"))

func logError(err error) {
	if err != nil {
		log.Println(err)
	}
}

func main() {
	logFile, err := os.OpenFile("errors.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		log.Println(err)
	}
	defer logFile.Close()

	log.SetOutput(logFile)

	mux := http.NewServeMux()
	// route naar url
	mux.HandleFunc("/", RootHandler)

	mux.HandleFunc("/Locatie", LocatieHandler)

	mux.HandleFunc("/Login", LoginHandler)

	mux.HandleFunc("/Booking", BookingHandler)
	mux.HandleFunc("/Logout", LogoutHandler)

	// read json file
	configBytes, err := ioutil.ReadFile("Db.json")
	if err != nil {
		logError(err)
	}

	// setting up new struct
	var config DatabaseConfig
	if err := json.Unmarshal(configBytes, &config); err != nil {
		log.Println(err)
	}

	// make connection database
	dbc = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", config.Username, config.Password, config.Host, config.Port, config.Database)
	db, err := sql.Open("mysql", dbc)
	if err != nil {
		logError(err)
	}
	defer db.Close()

	if err := db.Ping(); err != nil {
		log.Println(err)
	}

	http.ListenAndServe(":8080", mux)
}
type LoginResponse struct {
	Success bool
	UserID  int
}

func checkLogin(w http.ResponseWriter, r *http.Request) LoginResponse {
	username := r.FormValue("username")
	password := r.FormValue("password")

	db, err := sql.Open("mysql", dbc)
	if err != nil {
		log.Println(err)
		return LoginResponse{Success: false, UserID: -1}
	}
	defer db.Close()

	err = db.QueryRow("SELECT id FROM users WHERE username=? AND password=?", username, password).Scan(&userID)
	if err != nil {
		log.Println(err)
		return LoginResponse{Success: false, UserID: -1}
	}
	sessionID := createSession(userID)
	if sessionID == "" {
		log.Println("Error creating session")
		return LoginResponse{Success: false, UserID: -1}
	}
	sessionCookie := &http.Cookie{Name: "session_id", Value: sessionID, Path: "/", Expires: time.Now().Add(time.Duration(24) * time.Hour)}
	http.SetCookie(w, sessionCookie)
	return LoginResponse{Success: true, UserID: userID}
}
func RootHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, ` 		<h1>Fonteyn Vakantieparken</h1> 		<p>Vakantie parken voor een onvergeetelijke vakantie.</p> 		<ul> 			<li><a href="/Locatie">Locatie</a></li> 			<li><a href="/Login">Login</a></li> 		</ul> 	`)
}

func LocatieHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, ` 		<h1>Locatie</h1> 		<p>Wij zijn beschikbaar in meerder landen.</p> 		<ul> 			<li><a href="/">Home</a></li> 			<li><a href="/Login">Login</a></li> 		</ul> 	`)
}
func createSession(userID int) string {
	// Create a new session in the database and return the session ID
	db, err := sql.Open("mysql", dbc)
	if err != nil {
		log.Println(err)
		return ""
	}
	defer db.Close()

	// Create a unique session ID
	sessionID := fmt.Sprintf("%d_%d", userID, time.Now().UnixNano())
	_, err = db.Exec("INSERT INTO sessions (user_id, start_time, end_time) VALUES (?, NOW(), NOW())", userID)
	if err != nil {
		log.Println(err)
		return ""
	}

	return sessionID
}
func LoginHandler(w http.ResponseWriter, r *http.Request) {
	session, err := store.Get(r, "session-name")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return

	}
	session.Values["logged_in"] = false

	session.Save(r, w)
	if r.Method == http.MethodPost {
		loginResponse := checkLogin(w, r)
		if loginResponse.Success {
			http.Redirect(w, r, "/Booking", http.StatusFound)
			return
		}
	}
	fmt.Fprintln(w, `
    <h1>Fonteyn Vakantieparken</h1>
    <p>Vakantie parken voor een onvergeetelijke vakantie.</p>
    <form action="/Login" method="post">
        <label for="username">Username:</label>
        <input type="text" id="username" name="username">
        <br>
        <label for="password">Password:</label>
        <input type="password" id="password" name="password">
        <br><br>
        <input type="submit" value="Submit">
    </form>
`)
}
func LogoutHandler(w http.ResponseWriter, r *http.Request) {
	sessionCookie, _ := r.Cookie("session_id")
	sessionCookie.MaxAge = -1
	http.SetCookie(w, sessionCookie)
	http.Redirect(w, r, "/", http.StatusFound)
}

func BookingHandler(w http.ResponseWriter, r *http.Request) {
	// Check if the user is logged in
	session, err := store.Get(r, "session-name")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	// Als de gebruiker niet is ingelogd, verwijs de gebruiker door naar de inlogpagina
	if session.Values["logged_in"] != true {
		http.Redirect(w, r, "/login", http.StatusFound)
		return
	}
}

func validateSession(w http.ResponseWriter, r *http.Request, sessionID string) bool {
	db, err := sql.Open("mysql", dbc)
	if err != nil {
		log.Println(err)
		return false
	}
	defer db.Close()

	var userID int
	err = db.QueryRow("SELECT user_id FROM sessions WHERE id = ? AND end_time > NOW()", sessionID).Scan(&userID)
	if err != nil {
		log.Println(err)
		return false
	}
	if userID > 0 {
		session, err1 := store.Get(r, "session-name")

		if err1 != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return false
		}
		session.Values["logged_in"] = true
		session.Save(r, w)
		http.Redirect(w, r, "/booking", http.StatusFound)
		return true
	} else {
		return false
	}
}

更多关于Golang中Cookie重定向问题的解决方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

你好, 导入处理 Cookie 所需的必要包。在你的代码中,你导入了 “github.com/gorilla/sessions”,但使用方式不一致。请将导入更新为:

import (
	"github.com/gorilla/sessions"
	"net/http"
)

在你的 LoginHandler 函数中,将 “logged_in” 值设置为 true 后,需要保存会话。请按如下方式更新代码:

session, err := store.Get(r, "session-name")
if err != nil {
	http.Error(w, err.Error(), http.StatusInternalServerError)
	return
}

session.Values["logged_in"] = true
err = session.Save(r, w)
if err != nil {
	http.Error(w, err.Error(), http.StatusInternalServerError)
	return
}

http.Redirect(w, r, "/Booking", http.StatusFound)

请确保在你的 BookingHandler 函数中正确检索会话。

session, err := store.Get(r, "session-name")
if err != nil {
	http.Error(w, err.Error(), http.StatusInternalServerError)
	return
}

loggedIn, ok := session.Values["logged_in"].(bool)
if !ok || !loggedIn {
	http.Redirect(w, r, "/Login", http.StatusFound)
	return
}

// 继续处理其余的预订逻辑

使用安全的密钥配置你的 sessions.CookieStore 至关重要。请更新存储初始化代码以使用安全密钥:

store = sessions.NewCookieStore([]byte("your-secure-key-here"))

请记住将 "your-secure-key-here" 替换为一个强大且唯一的密钥。 请尝试这些建议,如果你遇到任何其他问题或有更多疑问,请随时在这里提问!

更多关于Golang中Cookie重定向问题的解决方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在你的代码中,Cookie重定向问题主要出现在会话管理逻辑不一致上。以下是需要修正的关键部分:

问题分析

  1. 双重会话管理冲突:同时使用了自定义Cookie和gorilla/sessions
  2. 会话状态未正确设置:登录成功后未设置gorilla session的logged_in标志
  3. 验证逻辑不完整BookingHandler缺少Cookie验证

修正后的代码

1. 修改LoginHandler

func LoginHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method == http.MethodPost {
        loginResponse := checkLogin(w, r)
        if loginResponse.Success {
            // 设置gorilla session
            session, err := store.Get(r, "session-name")
            if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }
            session.Values["logged_in"] = true
            session.Values["user_id"] = loginResponse.UserID
            session.Save(r, w)
            
            http.Redirect(w, r, "/Booking", http.StatusFound)
            return
        }
    }
    
    fmt.Fprintln(w, `
    <h1>Fonteyn Vakantieparken</h1>
    <p>Vakantie parken voor een onvergeetelijke vakantie.</p>
    <form action="/Login" method="post">
        <label for="username">Username:</label>
        <input type="text" id="username" name="username">
        <br>
        <label for="password">Password:</label>
        <input type="password" id="password" name="password">
        <br><br>
        <input type="submit" value="Submit">
    </form>
    `)
}

2. 修改BookingHandler

func BookingHandler(w http.ResponseWriter, r *http.Request) {
    // 检查gorilla session
    session, err := store.Get(r, "session-name")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    // 检查自定义session cookie
    sessionCookie, err := r.Cookie("session_id")
    if err != nil {
        http.Redirect(w, r, "/Login", http.StatusFound)
        return
    }
    
    // 验证数据库中的session
    if !validateSession(w, r, sessionCookie.Value) {
        http.Redirect(w, r, "/Login", http.StatusFound)
        return
    }
    
    // 检查登录状态
    if loggedIn, ok := session.Values["logged_in"].(bool); !ok || !loggedIn {
        http.Redirect(w, r, "/Login", http.StatusFound)
        return
    }
    
    // 显示预订页面
    fmt.Fprintln(w, `
    <h1>Booking Page</h1>
    <p>Welcome to the booking system!</p>
    <a href="/Logout">Logout</a>
    `)
}

3. 简化validateSession函数

func validateSession(w http.ResponseWriter, r *http.Request, sessionID string) bool {
    db, err := sql.Open("mysql", dbc)
    if err != nil {
        log.Println(err)
        return false
    }
    defer db.Close()
    
    var userID int
    err = db.QueryRow("SELECT user_id FROM sessions WHERE session_id = ? AND end_time > NOW()", sessionID).Scan(&userID)
    if err != nil {
        log.Println(err)
        return false
    }
    
    return userID > 0
}

4. 修正createSession函数

func createSession(userID int) string {
    db, err := sql.Open("mysql", dbc)
    if err != nil {
        log.Println(err)
        return ""
    }
    defer db.Close()
    
    sessionID := fmt.Sprintf("%d_%d", userID, time.Now().UnixNano())
    
    // 确保sessions表有正确的列名
    _, err = db.Exec("INSERT INTO sessions (user_id, session_id, start_time, end_time) VALUES (?, ?, NOW(), DATE_ADD(NOW(), INTERVAL 24 HOUR))", 
        userID, sessionID)
    if err != nil {
        log.Println(err)
        return ""
    }
    
    return sessionID
}

关键修改点

  1. 统一会话管理:在LoginHandler中同时设置自定义Cookie和gorilla session
  2. 双重验证:在BookingHandler中验证两种会话机制
  3. 正确的重定向:确保验证失败时重定向到登录页面
  4. 数据库一致性:修正session表的列名和查询逻辑

这些修改确保了Cookie创建、会话验证和重定向逻辑的一致性。

回到顶部