|
@@ -1,6 +1,7 @@
|
1
|
1
|
package main
|
2
|
2
|
|
3
|
3
|
import (
|
|
4
|
+ "container/heap"
|
4
|
5
|
"crypto/rand"
|
5
|
6
|
"encoding/base64"
|
6
|
7
|
"errors"
|
|
@@ -10,13 +11,68 @@ import (
|
10
|
11
|
)
|
11
|
12
|
|
12
|
13
|
type SessionData struct {
|
|
14
|
+ sid string
|
13
|
15
|
username string
|
|
16
|
+ priority time.Time
|
|
17
|
+ index int
|
|
18
|
+}
|
|
19
|
+
|
|
20
|
+type SessionQueue []*SessionData
|
|
21
|
+
|
|
22
|
+func (pq SessionQueue) Len() int {
|
|
23
|
+ return len(pq)
|
|
24
|
+}
|
|
25
|
+
|
|
26
|
+func (pq SessionQueue) Less(i, j int) bool {
|
|
27
|
+ return pq[i].priority.Before(pq[j].priority)
|
|
28
|
+}
|
|
29
|
+
|
|
30
|
+func (pq SessionQueue) Swap(i, j int) {
|
|
31
|
+ pq[i], pq[j] = pq[j], pq[i]
|
|
32
|
+ pq[i].index = i
|
|
33
|
+ pq[j].index = j
|
|
34
|
+}
|
|
35
|
+
|
|
36
|
+func (pq *SessionQueue) Push(x interface{}) {
|
|
37
|
+ n := len(*pq)
|
|
38
|
+ item := x.(*SessionData)
|
|
39
|
+ item.index = n
|
|
40
|
+ *pq = append(*pq, item)
|
|
41
|
+}
|
|
42
|
+
|
|
43
|
+func (pq *SessionQueue) Pop() interface{} {
|
|
44
|
+ old := *pq
|
|
45
|
+ n := len(old)
|
|
46
|
+ item := old[n-1]
|
|
47
|
+ item.index = -1 // for safety
|
|
48
|
+ *pq = old[0 : n-1]
|
|
49
|
+ return item
|
14
|
50
|
}
|
15
|
51
|
|
16
|
52
|
var (
|
17
|
|
- sessions = make(map[string]*SessionData)
|
|
53
|
+ sessions = make(map[string]*SessionData)
|
|
54
|
+ sessionQueue = make(SessionQueue, 0)
|
18
|
55
|
)
|
19
|
56
|
|
|
57
|
+func sessionExpirer() {
|
|
58
|
+ for {
|
|
59
|
+ for len(sessionQueue) > 0 && time.Now().After(sessionQueue[0].priority) {
|
|
60
|
+ session := heap.Pop(&sessionQueue).(*SessionData)
|
|
61
|
+ delete(sessions, session.sid)
|
|
62
|
+ }
|
|
63
|
+ time.Sleep(time.Second * 5)
|
|
64
|
+ }
|
|
65
|
+}
|
|
66
|
+
|
|
67
|
+func init() {
|
|
68
|
+ go sessionExpirer()
|
|
69
|
+}
|
|
70
|
+
|
|
71
|
+func addSession(data *SessionData) {
|
|
72
|
+ sessions[data.sid] = data
|
|
73
|
+ heap.Push(&sessionQueue, data)
|
|
74
|
+}
|
|
75
|
+
|
20
|
76
|
func userOk(username, password string) bool {
|
21
|
77
|
return (username == "Lamperi" && password == "paskaa")
|
22
|
78
|
}
|
|
@@ -32,20 +88,21 @@ func tryLogin(username, password string, longerTime bool) (http.Cookie, error) {
|
32
|
88
|
return http.Cookie{}, err
|
33
|
89
|
}
|
34
|
90
|
|
35
|
|
- sessions[sid] = &SessionData{username}
|
36
|
|
-
|
37
|
|
- hours := time.Duration(1)
|
|
91
|
+ duration := time.Hour * 1
|
38
|
92
|
if longerTime {
|
39
|
|
- hours = time.Duration(336)
|
|
93
|
+ duration = time.Hour * 24 * 14
|
40
|
94
|
}
|
41
|
95
|
|
42
|
96
|
loginCookie := http.Cookie{
|
43
|
97
|
Name: "id",
|
44
|
98
|
Value: sid,
|
45
|
|
- MaxAge: int((time.Hour * hours).Seconds()),
|
|
99
|
+ MaxAge: int(duration.Seconds()),
|
46
|
100
|
HttpOnly: true,
|
47
|
101
|
}
|
48
|
102
|
|
|
103
|
+ expiration := time.Now().Add(duration)
|
|
104
|
+ addSession(&SessionData{sid, username, expiration, 0})
|
|
105
|
+
|
49
|
106
|
return loginCookie, nil
|
50
|
107
|
}
|
51
|
108
|
|