csrf.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package csrf
  2. /*
  3. CSRF Token Management Module
  4. Author: tobychui
  5. This module handles the genreation and checking of a csrf token
  6. */
  7. import (
  8. "sync"
  9. "time"
  10. uuid "github.com/satori/go.uuid"
  11. "imuslab.com/arozos/mod/user"
  12. )
  13. type TokenManager struct {
  14. UserHandler *user.UserHandler
  15. csrfTokens *sync.Map //The token storage
  16. defaultTokenExpireTime int64 //The timeout for this token in seconds
  17. }
  18. type Token struct {
  19. ID string //The ID of the token
  20. Creator string //The username of the token creator
  21. CreationTime int64 //The creation time of this token
  22. Timeout int64 //The timeout for this token in seconds
  23. }
  24. //Create a new CSRF Token Manager
  25. func NewTokenManager(uh *user.UserHandler, tokenExpireTime int64) *TokenManager {
  26. tm := TokenManager{
  27. UserHandler: uh,
  28. csrfTokens: &sync.Map{},
  29. defaultTokenExpireTime: tokenExpireTime,
  30. }
  31. return &tm
  32. }
  33. //Generate a new token
  34. func (m *TokenManager) GenerateNewToken(username string) string {
  35. //Generate a new uuid as the token
  36. newUUID := uuid.NewV4().String()
  37. //Create a new token
  38. newToken := Token{
  39. ID: newUUID,
  40. Creator: username,
  41. CreationTime: time.Now().Unix(),
  42. Timeout: time.Now().Unix() + m.defaultTokenExpireTime,
  43. }
  44. //Save the user token
  45. userMap := m.GetUserTokenMap(username)
  46. userMap.Store(newUUID, newToken)
  47. return newUUID
  48. }
  49. func (m *TokenManager) GetUserTokenMap(username string) *sync.Map {
  50. usermap, ok := m.csrfTokens.Load(username)
  51. if !ok {
  52. //This user do not have his syncmap. Create one and save it
  53. userSyncMap := sync.Map{}
  54. m.csrfTokens.Store(username, &userSyncMap)
  55. return &userSyncMap
  56. } else {
  57. //This user sync map exists. Return the pointer of it
  58. userSyncMap := usermap.(*sync.Map)
  59. return userSyncMap
  60. }
  61. }
  62. //Check if a given token is valud
  63. func (m *TokenManager) CheckTokenValidation(username string, token string) bool {
  64. userSyncMap := m.GetUserTokenMap(username)
  65. tokenObject, ok := userSyncMap.Load(token)
  66. if !ok {
  67. return false
  68. } else {
  69. //Token exists. Check if it has expired
  70. currentTime := time.Now().Unix()
  71. thisToken := tokenObject.(Token)
  72. if thisToken.Timeout < currentTime {
  73. //Expired. Delete token
  74. userSyncMap.Delete(token)
  75. return false
  76. } else {
  77. userSyncMap.Delete(token)
  78. return true
  79. }
  80. }
  81. }
  82. func (m *TokenManager) ClearExpiredTokens() {
  83. currentTime := time.Now().Unix()
  84. m.csrfTokens.Range(func(username, usermap interface{}) bool {
  85. //For each user tokens
  86. thisUserTokenMap := usermap.(*sync.Map)
  87. thisUserTokenMap.Range(func(tokenid, tokenObject interface{}) bool {
  88. //For each token in this user
  89. thisTokenObject := tokenObject.(Token)
  90. if currentTime > thisTokenObject.Timeout {
  91. //This token has been expired. Remove it to save some space
  92. thisUserTokenMap.Delete(tokenid)
  93. }
  94. return true
  95. })
  96. return true
  97. })
  98. }