Golang Beego how to use sessions

18 January, 2017

The official documentation on using sessions in Beego is besides being outdated quite unclear. I'll show you how to use sessions inside your Beego application.

Introduction

There are few built in techniques on how to use sessions in your application, the most common one is "memory", in this case Beego will manage sessions in the application's memory itself. And storing everything in a key-value styled manner, but it will get garbage collected after a defined amount of time, if you rather wish to have session information to be stored permanent you can use the "file" method. However the memory and file methods are not an option if your website is running behind an loadbalancer over multiple machines, since the one machine will not be able to manage the memory and files of other machines. For such use case you'll have the built in option of using a database like Redis or MySQL to store your session data in.

Here is a list of builtin techniques

  • Memory: This, as explained, will store all session information within the application's memory, but it's prone for garbage collection and application restart
  • File: Beego will store everything in files, making it a tad slower but will store it indefinitely in files.
  • Redis: Here Beego will use a Redis server to store session data in, ideal for multiple applications sharing the same sessions.
  • MySQL: As like Redis, the data of the sessions will be stored in a MySQL database.

If you don't see your database of choice you can extend your application with a custom session module as explained here.

Assuming you have your Beego application up and running I'll show you how to use the memory technique.

Howto

Enable and setup sessions

The first step you'll have to do is enable sessions in your Beego application. Open the file under ./YourBeegoApplication/conf/app.conf and add the following line:

sessionon = true

This tells Beego on startup that you would like to have sessions enabled.

Next of you'll have to configure your sessions, do this by opening your main.go file, ./YourBeegoApplication/main.go

Firstly import the session package of Beego

import (
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/session"
)

and add the following lines to your main scope before the beego.Run() function.

func main() {
	sessionconf := &session.ManagerConfig{
		CookieName: "begoosessionID",
		Gclifetime: 3600,
	}
	beego.GlobalSessions, _ = session.NewManager("memory", sessionconf)
	go beego.GlobalSessions.GC()
	
	beego.Run()
}

It is very straight forward, you assign the global variable beego.GlobalSessions to a Beego session manager, which in this case uses the memory sessions and apply the the configuration to it.

CookieName will be, obviously, the name of the cookie that will hold the session id. And the Gclifetime is to tell when a session has to be garbage collected. You can pass more settings to the NewManager.

The go routine will take care of cleaning up the sessions which are past expiration time and garbage collect them.

Using sessions in your controllers

As an example for this tutorial I'll be showing a simple user authentication, a controller that logs a user in (set), a controller that checks if a user is logged in (get) and a controller that logs a user out (delete).

Logging an user in

Imagine a login form has been posted to a LoginController.

func (this *LoginController) Post() {
	// Check if user is logged in
	session := this.StartSession()
	userID := session.Get("UserID")
	
	if userID != nil {
		// User is logged in already, display another page
		return
	}
	
	// Do input checks
	
	// Set the UserID if everything is ok
	session.Set("UserID", 50)
}

We first start the session, this probably looks like a common practice if you have experience in PHP. We check if the user is logged in already, if not we do input checks, database lookups and if everything is correct, set the user as logged in by identifying the user in the session by the ID.

You can pas an interface to the second parameter of the Set() function.

If you call with Get() to an non existing key it will return nil, meaning it's not set.

Show content that requires to be logged in

func (this *UserLoginRequiredController) Get() {
	// Check if user is logged in
	session := this.StartSession()
	userID := session.Get("UserID")
	
	if userID == nil {
		// UserID is not set, display another page
		return
	}
	
	// Display page that requires to be logged in
}

Log the user out

func (this *LogoutController) Get() {
	// Check if user is logged in
	session := this.StartSession()
	userID := session.Get("UserID")
	if userID != nil {
		// UserID is set and can be deleted
		session.Delete("UserID")
	}
}

 We have to check first if the ID in the session is set before deleting it, else it causes an error.

Automatically start a session

If you don't want to write the same this.StartSession() line in every controller that requires sessions, there is a different blog post that I wrote which you can apply to this problem. In short; you can inherit the beego.Controller structure in a custom structure, set a member variable that stores the session.Store in it like this:

package controllers

import (
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/session"
)

type ExtendedController struct {
	beego.Controller
	Session session.Store
}

func (this *ExtendedController) Prepare() {
	this.Session = this.StartSession()
}

And now you can create controller with 'ExtendedController' instead of beego.Controller and call the member Session inside your functions.

Resources and good reads