Help with golang website and redirect

Hello Guys,
I just build this golang website the DB connection works and session are getting loged and the login is working but the redirect to booking doesnt work. are you guys able to help me i dont know whats going wrong. It just loads the login again and doesnt redirect, further debugging doesnt seem te give me anything.

Github: GitHub - KSCHNAPPIEN/golang-web

package main

import (
“database/sql”
“encoding/json”
“fmt”
“io/ioutil”
“log”
“net/http”
“os”

_ "github.com/go-sql-driver/mysql"

)

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

var dbc string

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)

// 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)

}
func checkLogin(r *http.Request) bool {
// get usename and password
username := r.FormValue(“username”)
password := r.FormValue(“password”)

// Connect to the database
db, err := sql.Open("mysql", dbc)
if err != nil {
	log.Println(err)
	return false
}
defer db.Close()

// Execute a SELECT query to check if the username and password are correct
var userID int
err = db.QueryRow("SELECT id FROM users WHERE username=? AND password=?", username, password).Scan(&userID)
if err != nil {
	log.Println(err)
	return false
}

// If the username and password are correct, insert a new session into the database
_, err = db.Exec("INSERT INTO sessions (user_id, start_time, end_time) VALUES (?, NOW(), NOW())", userID)
if err != nil {
	log.Println(err)
	return false
}

return true

}
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 BookingHandler(w http.ResponseWriter, r *http.Request) {
// Check if user is logged in
if !checkLogin(r) {
http.Redirect(w, r, “/Login”, http.StatusSeeOther)
return
}
}
func LoginHandler(w http.ResponseWriter, r *http.Request) {
// display login
fmt.Fprintln(w, <h1>Fonteyn Vakantieparken</h1> <h2>Inloggen</h2> <form action="/Login" method="POST"> <label for="username">Gebruikersnaam:</label><br> <input type="text" id="username" name="username"><br> <label for="password">Wachtwoord:</label><br> <input type="password" id="password" name="password"><br><br> <input type="submit" value="Inloggen"> </form> )
if r.Method == “POST” {
if checkLogin(r) {
http.Redirect(w, r, “/Booking”, http.StatusSeeOther)
return
} else {
fmt.Fprintln(w, “Invalid username or password.”)
}
}
}

Your redirect does work. POST /Login redirects to /Booking
But /Booking redirects back to /Login, because it checks for the login form data again, which is missing.

You need to save the session to the browser somehow, (e.g. with a cookie).

Also, your Login() function should print the login form only if the Method is GET.

I forked your repository and added an example cookie to track the user, here:

I replaced the database with hardcoded users.

is there any other way besides cookies to track the user i tought the session i added would do the job

There are several ways, but they all have to interact with the browser. Otherwise how would the server know which user makes a request?
I recently found this article that mentions some mechanisms:

BasicAuth is a simple mechanism, if you are ok with its shortcomings. Checking the password can even be done outside the application, e.g. from nginx or haproxy in front of your application. Then all the application needs to do is to get the username from the HTTP headers. But you’d have to figure out your own way of administering passwords. I use it for personal single-user projects.

By the way, storing the password in the database using cleartext is bad practice. Anyone who gets access to the database, including you, would have access to the passwords of all your users. You should store a hashed password, using something like golang.org/x/crypto/bcrypt.

Web authentication is complicated and prone to security issues. I’m currently investigating the options myself.

1 Like

How would you do it with cookies in a save manner?
got a example?

I gave you an example of how to put a session id in a cookie. The session id should be sufficiently long and random so it cannot be guessed. It should also have the HttpOnly attribute so it cannot be accessed by Javascript. You can generate such a session id, save it in your sessions table, and put it in the cookie.

The next thing about cookies is to avoid CSRF attacks when implementing forms or other pages that can change things that only the user should be able to change. The way to do this is to add a token to the form or url, that is similar to a session id (but different).

I’m learning how to do this myself. Here’s some advice that I found on how to do this, but it’s in PHP:

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.