manager.go
package sessions
import (
"crypto/rand"
"encoding/base64"
"errors"
"io"
"net/http"
)
type Manager struct {
database map[string]interface{}
}
var mg Manager
func NewManager() *Manager {
return &mg
}
func (m *Manager) NewSessionID() string {
b := make([]byte, 64)
if _, err := io.ReadFull(rand.Reader, b); err != nil {
return ""
}
return base64.URLEncoding.EncodeToString(b)
}
fun (m *Manager) New(r *http.Request, cookieName string)(*Session, error){
cookie, err := r.Cookie(cookie.Name)
if err == nil && m.Exists(cookie.Value){
return nil, errors.New("sessionIDは既に発行されています")
}
session := NewSession(m, cookieName)
session.ID = m.NewSessionID()
session.request = r
return session, nil
}
func(m *Manager) Save(r *http.Request, w http.ResponseWriter, session *Session) error {
m.database[session.ID] = session
c := &http.Cookie {
Name: session.Name(),
Value: session.ID,
Path: "/",
}
http.SetCookie(session.writer, c)
return nil
}
func(m *Manager) Exists(sessionID string) bool {
_, r = m.database[sessionID]
return r
}
func(m *Manager) Get(r *http.Request, cookieName string)(*Session, error){
cookie, err := r.Cookie(cookieName)
if err != nil {
return nil, err
}
sessionID := cookie.Value
buffer, exists := m.database[sessionID]
if !exists {
return nil, errors.New("無効なセッションIDです")
}
session := buffer.(*Session)
session.request = r
return session, nil
}
func(m *Manager) Destroy(sessionID string){
delete(m.database, sessionID)
}
session.go
package sessions
import(
"net/http"
"github.com/gin-gonic/gin"
"github.com/gorilla/context"
)
const (
DefaultSessionName = "default-session"
DefaultCookieName = "default-cookie"
)
type Session struct {
cookieName string
ID string
manager *Manager
request *http.request
writer http.ResponseWriter
Values map[string]interface{}
}
func NewSession(manager *Manager, cookieName string) *Session {
return &Session {
cookieName: cookieName,
manager: manager,
Values: map[string]interface{}{},
}
}
func StartSession(sessionName, cookieName string, manager *Manager) gin.HandlerFunc {
return func(ctx *gin.Context){
var session *Session
var err error
session, err = manager.Get(ctx.Request, cookieName)
if err != nil {
session, err = manager.New(ctx.Request, cookieName)
if err != nil {
println(err.Error())
ctx.Abort()
}
}
session.writer = ctx.Writer
ctx.Set(sessionName, session)
defer context.Clear(ctx.Request)
ctx.Next()
}
}
func StartDefaultSession(manager *Manager) gin.HandlerFunc {
return StartSession(DefaultSessionName, DefaultCookieName, manager)
}
func GetSession(c *gin.Context, sessionName string) *Session {
return c.MustGet(sessionName).(*Session)
}
func GetDefaultSession(c *gin.Context) *Session {
return GetSession(c, DefaultSessionName)
}
func (s *Session) Save() error {
return s.manager.Save(s.request, s.writer, s)
}
func (s *Session) Name() string {
return s.cookieName
}
func (s *Session) Get(key string)(interface{}, bool){
ret, exists := s.Value[key]
return ret, exists
}
func(s *Session) Set(key string, val interface{}){
s.Values[key] = val
}
func(s *Session) Delete(key string){
delete(s.Values, key)
}
func(s *Session) Terminate(){
s.manager.Destroy(s.ID)
}
h_Login.go
package req_handler
import (
"fmt"
"html/template"
"net/http"
)
func HandlerLogin(w http.ResponseWrite, req *http.Request){
tpl := template.Must(template.ParseFiles("templates/login.gtpl"))
values := map[string]string{}
if err := tpl.ExecuteTemplate(w, "login.gtpl", values); err != nil {
fmt.Println(err)
}
}
fun HandlerExecLogin(w http.ResponseWriter, req *http.Request){
manager := sessions.NewManager()
sessions.StartDefaultSession(manager)
session := manager.Get(req, sessions.DefaultCookieName)
session.Set("account", req.FormValue("account"))
session.Save()
http.Redirect(w, req, "http://192.168.34.10:10443/login-top", 301)
}
h_LoginTop.go
package req_handler
import (
"fmt"
"html/template"
"net/http"
)
func HandlerLoginTop(w http.ResponseWriter, r *http.Request){
tpl := template.Must(template.ParseFiles("templates/login-top.gtpl"))
isLoggedIn := ""
account := ""
session := manager.Get(req, sessions.DefaultCookieName)
if session.Values["account"]{
isLoggedIn = "isLoggedIn"
account = session.Values["account"]
}
values := map[string] string {
"isLoggedIn": isLoggedIn,
"account": account,
}
if err := tpl.ExecuteTemplate(w, "login-top.gtpl", values); err != nil {
fmt.Println(err)
}
}
func HandlerExecLogout(w http.ResponseWriter, req *http.Request){
session := manager.Get(req, sessions.DefaultCookieName)
session.Terminate()
http.Redirect(w, req, "https://192.168.34.10:10443/login", 301)
}
なるほど、ginね
1. usersテーブルでユーザ名とパスワードが一致するかチェックして、一致した場合進めるようにする
2. sessionで管理する
セッションの使い方は覚えていけば良さそう