Handling HTTP sessions and cookies in Go can be accomplished using the net/http
package, which provides a simple API for managing both sessions and cookies.
Handling Cookies
Cookies can be read from an incoming request and set on outgoing responses.
Reading Cookies from a Request
To read cookies from an incoming request:
func handler(w http.ResponseWriter, r *http.Request) {
// Get a cookie named "session_token"
cookie, err := r.Cookie("session_token")
if err != nil {
if err == http.ErrNoCookie {
// The cookie is not set
// Handle the absence of the cookie
} else {
// Some other error occurred
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
// Use cookie.Value to do something
sessionToken := cookie.Value
// ... rest of the handler
}
Setting Cookies in a Response
To set cookies in an HTTP response:
func handler(w http.ResponseWriter, r *http.Request) {
// Create a new cookie
cookie := &http.Cookie{
Name: "session_token",
Value: "some-session-token",
Expires: time.Now().Add(24 * time.Hour), // 1 day expiration
HttpOnly: true, // Prevents JavaScript access to the cookie
}
// Set the cookie on the response
http.SetCookie(w, cookie)
// ... rest of the handler
}
Handling Sessions
Go does not have a built-in session management system. To handle sessions, you generally use a combination of cookies and server-side storage.
Implementing Session Management
Here's a basic example of how you might implement session management using cookies and a simple in-memory store for sessions. In a production environment, you would likely use a database or a distributed cache like Redis for storing session data.
package main
import (
"net/http"
"github.com/gorilla/sessions"
)
// Store will hold all session data
var store = sessions.NewCookieStore([]byte("secret-key"))
func loginHandler(w http.ResponseWriter, r *http.Request) {
// Authentication logic goes here ...
// If authentication is successful:
session, _ := store.Get(r, "session-name")
session.Values["authenticated"] = true
session.Save(r, w)
// Redirect to the protected area
http.Redirect(w, r, "/protected", http.StatusFound)
}
func protectedHandler(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, "session-name")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Check if the user is authenticated
if auth, ok := session.Values["authenticated"].(bool); !ok || !auth {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
// The user is authenticated
// Serve the protected resource
w.Write([]byte("Protected content."))
}
func logoutHandler(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-name")
// Revoke users authentication
session.Values["authenticated"] = false
session.Save(r, w)
// Redirect to the login page
http.Redirect(w, r, "/login", http.StatusFound)
}
func main() {
http.HandleFunc("/login", loginHandler)
http.HandleFunc("/protected", protectedHandler)
http.HandleFunc("/logout", logoutHandler)
http.ListenAndServe(":8080", nil)
}
In this example, we're using the gorilla/sessions
package, which provides additional functionality over the built-in net/http
cookie management. You can install the package by running:
go get github.com/gorilla/sessions
Remember to replace the "secret-key" with a strong, randomly generated key to secure your sessions.
Always ensure to follow best practices for security, especially when it comes to handling user sessions. Use HTTPS to prevent cookie theft, set the Secure
attribute on cookies, and avoid exposing any sensitive data through cookies.