auth.go 2.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package main
  2. import (
  3. "container/heap"
  4. "crypto/rand"
  5. "encoding/base64"
  6. "errors"
  7. "log"
  8. "net/http"
  9. "time"
  10. )
  11. type SessionData struct {
  12. sid string
  13. username string
  14. priority time.Time
  15. index int
  16. }
  17. type SessionQueue []*SessionData
  18. func (pq SessionQueue) Len() int {
  19. return len(pq)
  20. }
  21. func (pq SessionQueue) Less(i, j int) bool {
  22. return pq[i].priority.Before(pq[j].priority)
  23. }
  24. func (pq SessionQueue) Swap(i, j int) {
  25. pq[i], pq[j] = pq[j], pq[i]
  26. pq[i].index = i
  27. pq[j].index = j
  28. }
  29. func (pq *SessionQueue) Push(x interface{}) {
  30. n := len(*pq)
  31. item := x.(*SessionData)
  32. item.index = n
  33. *pq = append(*pq, item)
  34. }
  35. func (pq *SessionQueue) Pop() interface{} {
  36. old := *pq
  37. n := len(old)
  38. item := old[n-1]
  39. item.index = -1 // for safety
  40. *pq = old[0 : n-1]
  41. return item
  42. }
  43. var (
  44. sessions = make(map[string]*SessionData)
  45. sessionQueue = make(SessionQueue, 0)
  46. )
  47. func sessionExpirer() {
  48. for {
  49. for len(sessionQueue) > 0 && time.Now().After(sessionQueue[0].priority) {
  50. session := heap.Pop(&sessionQueue).(*SessionData)
  51. delete(sessions, session.sid)
  52. }
  53. time.Sleep(time.Second * 5)
  54. }
  55. }
  56. func init() {
  57. go sessionExpirer()
  58. }
  59. func addSession(data *SessionData) {
  60. sessions[data.sid] = data
  61. heap.Push(&sessionQueue, data)
  62. }
  63. func userOk(username, password string) bool {
  64. return (username == "Lamperi" && password == "paskaa")
  65. }
  66. func tryLogin(username, password string, longerTime bool) (http.Cookie, error) {
  67. if exists := userOk(username, password); !exists {
  68. return http.Cookie{},
  69. errors.New("The username or password you entered isn't correct.")
  70. }
  71. sid, err := randString(32)
  72. if err != nil {
  73. return http.Cookie{}, err
  74. }
  75. duration := time.Hour * 1
  76. if longerTime {
  77. duration = time.Hour * 24 * 14
  78. }
  79. loginCookie := http.Cookie{
  80. Name: "id",
  81. Value: sid,
  82. MaxAge: int(duration.Seconds()),
  83. HttpOnly: true,
  84. }
  85. expiration := time.Now().Add(duration)
  86. addSession(&SessionData{sid, username, expiration, 0})
  87. return loginCookie, nil
  88. }
  89. func getSession(req *http.Request) (*SessionData, error) {
  90. cookie, err := req.Cookie("id")
  91. if err != nil {
  92. return nil, err
  93. }
  94. session, exists := sessions[cookie.Value]
  95. if !exists {
  96. return nil, errors.New("Session expired from server")
  97. }
  98. return session, nil
  99. }
  100. func randString(size int) (string, error) {
  101. buf := make([]byte, size)
  102. if _, err := rand.Read(buf); err != nil {
  103. log.Println(err)
  104. return "", errors.New("Couldn't generate random string")
  105. }
  106. return base64.URLEncoding.EncodeToString(buf)[:size], nil
  107. }