session

package module
v0.0.0-...-3778879 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 4, 2018 License: MIT Imports: 8 Imported by: 8

README

gin-jwt-session

GoDoc Go Report

Description

gin-jwt-session is a Go package that provides JWT and Session for Gin framework

It already been adopt as one of gin gin-contrib formal middleware

It has the following features:

  • Provide JWT tokenstring generate and validate function.
  • Provide defautlt secured session
  • Provide secured flashes functions
  • Simple to use and also allow you manual adjust options if necessary
  • Provide sample for you to easily follow up

Requirements

Go 1.6 or above.

Installation

Run the following command to install the package:

go get github.com/ScottHuangZL/gin-jwt-session

Getting Started

As for example please refer to gin-jwt-session-example.

package main

import (
	"context"
	"github.com/ScottHuangZL/gin-jwt-session"
	"github.com/ScottHuangZL/gin-jwt-session/example/controllers"
	"github.com/ScottHuangZL/gin-jwt-session/example/models"
	"github.com/gin-gonic/gin"
	"html/template"
	"log"
	"net/http"
	"os"
	"os/signal"
	"time"
)

func main() {
	r := gin.Default()
	//below are optional setting, you change it or just comment it to let it as default
	// session.SecretKey = "You any very secriet key !@#$!@%@"  //Any characters
	// session.JwtTokenName = "YouCanChangeTokenName"               //no blank character
	// session.DefaultFlashSessionName = "YouCanChangeTheFlashName" //no blank character
	// session.DefaultSessionName = "YouCanChangeTheSessionName"    //no blank character
	//end of optional setting
	session.NewStore()
	r.Use(session.ClearMiddleware()) //important to avoid mem leak
	setupRouter(r)

	s := &http.Server{
		Addr:           ":8080",
		Handler:        r,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}

	go func() {
		// service connections
		if err := s.ListenAndServe(); err != nil {
			log.Printf("listen: %s\n", err)
		}
	}()
	// Wait for interrupt signal to gracefully shutdown the server with
	// a timeout of 5 seconds.
	quit := make(chan os.Signal)
	signal.Notify(quit, os.Interrupt)
	<-quit
	log.Println("Shutdown Server ...")

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := s.Shutdown(ctx); err != nil {
		log.Fatal("Server Shutdown:", err)
	}
	log.Println("Server exiting")
}

func setupRouter(r *gin.Engine) {
	r.Delims("{%", "%}")
	// Default With the Logger and Recovery middleware already attached
	// Set a lower memory limit for multipart forms (default is 32 MiB)
	r.MaxMultipartMemory = 8 << 20 // 8 MiB
	r.Static("/static", "./static")
	r.SetFuncMap(template.FuncMap{
		"formatAsDate": model.FormatAsDate,
	})
	r.LoadHTMLGlob("views/**/*")
	r.GET("/login", controllers.LoginHandler)
	r.GET("/logout", controllers.LoginHandler) //logout also leverage login handler, since it just need clear session
	r.POST("/validate-jwt-login", controllers.ValidateJwtLoginHandler)
	r.GET("/index.html", controllers.HomeHandler)
	r.GET("/index", controllers.HomeHandler)
	r.GET("", controllers.HomeHandler)

	r.GET("/some-cookie-example", controllers.SomeCookiesHandler)

	r.GET("/ping", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{"ping": "pong"})
	})

}
package controllers

import (
	"github.com/ScottHuangZL/gin-jwt-session"
	"github.com/ScottHuangZL/gin-jwt-session/example/models"
	"github.com/gin-gonic/gin"
	// "log"
	"net/http"
	"time"
)

//LoginHandler for login page , it also can use for logout since it delete all stored session
func LoginHandler(c *gin.Context) {
	flashes := session.GetFlashes(c)
	session.DeleteAllSession(c)
	c.HTML(http.StatusOK, "home/login.html", gin.H{
		"title":   "Jwt Login",
		"flashes": flashes,
	})

}

//HomeHandler is the home handler
//will show home page, also according login/logout action to navigate
func HomeHandler(c *gin.Context) {
	// action := strings.ToLower(c.Param("action"))
	// path := strings.ToLower(c.Request.URL.Path)

	flashes := session.GetFlashes(c)
	username, err := session.ValidateJWTToken(c)
	loginFlag := false
	if err == nil && username != "" {
		loginFlag = true
	}
	c.HTML(http.StatusOK, "home/index.html", gin.H{
		"title":     "Main website",
		"now":       time.Now(),
		"flashes":   flashes,
		"loginFlag": loginFlag,
		"username":  username,
	})
}

//ValidateJwtLoginHandler validate the login and redirect to correct link
func ValidateJwtLoginHandler(c *gin.Context) {
	var form model.Login
	//try get login info
	if err := c.ShouldBind(&form); err != nil {
		session.SetFlash(c, "Get login info error: "+err.Error())
		c.Redirect(http.StatusMovedPermanently, "/login")
		return
	}
	//validate login info
	if ok := model.ValidateUser(form.Username, form.Password); !ok {
		session.SetFlash(c, "Error : username or password")
		c.Redirect(http.StatusMovedPermanently, "/login")
		return
	}
	//login info is correct, can generate JWT token and store in clien side now
	tokenString, err := session.GenerateJWTToken(form.Username, time.Hour*time.Duration(1))
	if err != nil {
		session.SetFlash(c, "Error Generate token string: "+err.Error())
		c.Redirect(http.StatusMovedPermanently, "/login")
		return
	}

	err = session.SetTokenString(c, tokenString, 60*60) //60 minutes
	if err != nil {
		session.SetFlash(c, "Error set token string: "+err.Error())
		c.Redirect(http.StatusMovedPermanently, "/login")
		return
	}
	session.SetFlash(c, "success : successful login")
	session.SetFlash(c, "username : "+form.Username)
	c.Redirect(http.StatusMovedPermanently, "/")
	return
}

//SomeCookiesHandler show cookie example
func SomeCookiesHandler(c *gin.Context) {
	session.Set(c, "hello", "world")
	sessionMessage, _ := session.GetString(c, "hello")
	session.Set(c, "hello", 2017)
	message2, _ := session.GetInt(c, "hello")
	session.Delete(c, "hello")
	readAgain, _ := session.GetString(c, "hello")
	c.JSON(http.StatusOK, gin.H{
		"session message":                 sessionMessage,
		"session new message":             message2,
		"session read again after delete": readAgain,
		"status": http.StatusOK})
}

Credits

gin-jwt-session backend leverage github.com/gorilla/sessions github.com/dgrijalva/jwt-go

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (

	//SecretKey to encrypt session
	//please clear the browser buffer(ctrl+shift+delete) in case you change the key and token name to new one
	SecretKey = "welcome to Scott Huang's Session and JWT util, please change to your secret accodingly."

	//JwtTokenName is JWT token name, also is the JWT session name too
	//Not too long and also do not include blank, such as do not set as "a blank name"
	JwtTokenName = "jwtTokenSession"

	//DefaultFlashSessionName to store the flash session
	//Not too long and also do not include blank, such as do not set as "a blank name"
	DefaultFlashSessionName = "myDefaultFlashSessionName"

	//DefaultSessionName to store other session message
	//Not too long and also do not include blank, such as do not set as "a blank name"
	DefaultSessionName = "myDefaultSessionName"

	//DefaultOption to provide default option
	//Maxage set the session duration by second
	DefaultOption = &sessions.Options{
		Path:     "/",
		MaxAge:   3600 * 1,
		HttpOnly: true,
	}
)

Functions

func ClearMiddleware

func ClearMiddleware() gin.HandlerFunc

ClearMiddleware clear mem to avoid leak. you should add this middleware at your main gin.router

Please see note from http://www.gorillatoolkit.org/pkg/sessions Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory! ClearHandler actually invoke Clear func

func Delete

func Delete(c *gin.Context, key interface{}) (err error)

Delete try delete default session key value

func DeleteAllSession

func DeleteAllSession(c *gin.Context)

DeleteAllSession will delete JwtTokenName/DefaultSessionName/DefaultFlashSessionName usually used when user logout

func DeleteNormalSession

func DeleteNormalSession(c *gin.Context)

DeleteNormalSession will delete DefaultSessionName and DefaultFlashSessionName

func DeleteSession

func DeleteSession(c *gin.Context, sessionName string) (err error)

DeleteSession delete a session instead of Set, the delete will set MaxAge to -1

func DeleteSessionValue

func DeleteSessionValue(c *gin.Context, sessionName string, key interface{}) (err error)

DeleteSessionValue try delete the gived session key value

func DeleteTokenSession

func DeleteTokenSession(c *gin.Context) (err error)

DeleteTokenSession delete before generate JWT token string

func GenerateJWTToken

func GenerateJWTToken(username string, tokenDuration time.Duration) (tokenString string, err error)

GenerateJWTToken per gived username and token duration

Claims example as below, and we only use below top 3 claims

"iat": 1416797419, //start
"exp": 1448333419, //end
"sub": "jrocket@example.com",  //username

"iss": "Online JWT Builder",
"aud": "www.example.com",
"GivenName": "Johnny",
"Surname": "Rocket",
"Email": "jrocket@example.com",
"Role": [ "Manager", "Project Administrator" ]

func GetDefaultSessionValue

func GetDefaultSessionValue(c *gin.Context, key interface{}) (value interface{}, err error)

GetDefaultSessionValue levarage GetSessionValue to get key value

func GetFlashes

func GetFlashes(c *gin.Context) []interface{}

GetFlashes return previously flashes from default session

func GetInt

func GetInt(c *gin.Context, key interface{}) (value int, err error)

GetInt levarage Get to get key value and convert to int

func GetSessionFlashes

func GetSessionFlashes(c *gin.Context, sessionName string) []interface{}

GetSessionFlashes return previously flashes per gived session

func GetSessionValue

func GetSessionValue(c *gin.Context, sessionName string, key interface{}) (value interface{}, err error)

GetSessionValue session value according The base get func, other will leverage this func

func GetString

func GetString(c *gin.Context, key interface{}) (value string, err error)

GetString levarage Get to get key value and convert to string

func GetTokenString

func GetTokenString(c *gin.Context) (tokenString string, err error)

GetTokenString to get tokenString

func NewStore

func NewStore()

NewStore only create one session store globally The main program need call sessions.NewStore() to initialize store User also can set sessions var before call this function to adjust some default parameters

Usage Sample:

//in your main(), setup session after r = gin.Default()
sessions.JwtTokenName = "YourJWTTokenName"                       //string without blank
sessions.DefaultSessionName = "YourDefaultSessionName"           //string without blank
sessions.DefaultFlashSessionName = "YourDefaultFlashSessionName" //string without blank
sessions.SecretKey = "Your Secerect Key (*&%(&*%$"               //string with any
sessions.NewStore()                                              //setup the session store
r.Use(sessions.ClearMiddleware())                                //important to avoid memory leak
//end setup session

func Set

func Set(c *gin.Context, key, value interface{}) (err error)

Set set key value by interface

func SetFlash

func SetFlash(c *gin.Context, flash interface{}) (err error)

SetFlash set new flash to default session

func SetMessage

func SetMessage(c *gin.Context, message Message) (err error)

SetMessage will set session into gin.Context per gived SesionMessage It is the basic function for other set func to leverage

Usage Sample:

 err := sessions.SetMessage(c,
	sessions.Message{
		Key:   sessions.JwtTokenName,
		Value: tokenString,
		// SessionName: "",
		// Options: &sessions.Options{
		// 	Path:     "/",
		// 	MaxAge:   3600 * 1, //1 hour for session. Btw, the token itself have valid period, so, better set it as same
		// 	HttpOnly: true,
		// },
	})

func SetSessionFlash

func SetSessionFlash(c *gin.Context, flash Flash) (err error)

SetSessionFlash set new flash to givied session

func SetTokenString

func SetTokenString(c *gin.Context, tokenString string, seconds int) (err error)

SetTokenString into JwtTokenSession

func ValidateJWTToken

func ValidateJWTToken(c *gin.Context) (username string, err error)

ValidateJWTToken valide JWT per headder firstly And then try get from session if above failed will return valid username in case no err username == "" also mean failed

Types

type Flash

type Flash struct {
	Flash       interface{}
	SessionName string
}

Flash type to contain new flash and its session

type Message

type Message struct {
	Key         interface{}
	Value       interface{}
	SessionName string
	Options     *sessions.Options
}

Message struct contain message you would like to set in session usually you just provide Key and Value only

type Options

type Options = sessions.Options

Options stores configuration for a session or session store. Fields are a subset of http.Cookie fields.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL