123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- package main
-
- import (
- "container/heap"
- "crypto/rand"
- "encoding/base64"
- "errors"
- "log"
- "net/http"
- "time"
- )
-
- type SessionData struct {
- sid string
- username string
- priority time.Time
- index int
- }
-
- type SessionQueue []*SessionData
-
- func (pq SessionQueue) Len() int {
- return len(pq)
- }
-
- func (pq SessionQueue) Less(i, j int) bool {
- return pq[i].priority.Before(pq[j].priority)
- }
-
- func (pq SessionQueue) Swap(i, j int) {
- pq[i], pq[j] = pq[j], pq[i]
- pq[i].index = i
- pq[j].index = j
- }
-
- func (pq *SessionQueue) Push(x interface{}) {
- n := len(*pq)
- item := x.(*SessionData)
- item.index = n
- *pq = append(*pq, item)
- }
-
- func (pq *SessionQueue) Pop() interface{} {
- old := *pq
- n := len(old)
- item := old[n-1]
- item.index = -1 // for safety
- *pq = old[0 : n-1]
- return item
- }
-
- var (
- sessions = make(map[string]*SessionData)
- sessionQueue = make(SessionQueue, 0)
- )
-
- func sessionExpirer() {
- for {
- for len(sessionQueue) > 0 && time.Now().After(sessionQueue[0].priority) {
- session := heap.Pop(&sessionQueue).(*SessionData)
- delete(sessions, session.sid)
- }
- time.Sleep(time.Second * 5)
- }
- }
-
- func init() {
- go sessionExpirer()
- }
-
- func addSession(data *SessionData) {
- sessions[data.sid] = data
- heap.Push(&sessionQueue, data)
- }
-
- func userOk(username, password string) bool {
- return (username == "Lamperi" && password == "paskaa")
- }
-
- func tryLogin(username, password string, longerTime bool) (http.Cookie, error) {
- if exists := userOk(username, password); !exists {
- return http.Cookie{},
- errors.New("The username or password you entered isn't correct.")
- }
-
- sid, err := randString(32)
- if err != nil {
- return http.Cookie{}, err
- }
-
- duration := time.Hour * 1
- if longerTime {
- duration = time.Hour * 24 * 14
- }
-
- loginCookie := http.Cookie{
- Name: "id",
- Value: sid,
- MaxAge: int(duration.Seconds()),
- HttpOnly: true,
- }
-
- expiration := time.Now().Add(duration)
- addSession(&SessionData{sid, username, expiration, 0})
-
- return loginCookie, nil
- }
-
- func getSession(req *http.Request) (*SessionData, error) {
- cookie, err := req.Cookie("id")
- if err != nil {
- return nil, err
- }
-
- session, exists := sessions[cookie.Value]
- if !exists {
- return nil, errors.New("Session expired from server")
- }
- return session, nil
- }
-
- func randString(size int) (string, error) {
- buf := make([]byte, size)
-
- if _, err := rand.Read(buf); err != nil {
- log.Println(err)
- return "", errors.New("Couldn't generate random string")
- }
-
- return base64.URLEncoding.EncodeToString(buf)[:size], nil
- }
|