auth_service.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package service
  2. import (
  3. "crypto/md5"
  4. "encoding/base64"
  5. "encoding/hex"
  6. "encoding/json"
  7. "errors"
  8. "fmt"
  9. "math/rand"
  10. "strings"
  11. "sync"
  12. "time"
  13. "github.com/boltdb/bolt"
  14. "github.com/dgrijalva/jwt-go"
  15. "github.com/pborman/uuid"
  16. "gopkg.in/redis.v2"
  17. "xiaoniaokuaiyan.com/xiaoniao/config"
  18. server "xiaoniaokuaiyan.com/xiaoniao/server"
  19. "xiaoniaokuaiyan.com/xiaoniao/util"
  20. )
  21. type AuthService struct {
  22. server.AuthService
  23. }
  24. func GenerateToken(clientId string) *server.AuthToken {
  25. token := uuid.NewRandom()
  26. tokenStr := strings.TrimRight(base64.URLEncoding.EncodeToString([]byte(token)), "=")
  27. return &server.AuthToken{
  28. AccessToken: tokenStr,
  29. TokenType: "Bearer",
  30. Expiry: util.Time{time.Now().Add(time.Hour)},
  31. ClientId: clientId,
  32. }
  33. }
  34. func (auth *AuthService) GetAccessToken(strToken string) (interface{}, error) {
  35. token, err := jwt.Parse(strToken, func(token *jwt.Token) (interface{}, error) {
  36. if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
  37. return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
  38. }
  39. //db, err := bolt.Open("auth.db", 0666, &bolt.Options{ReadOnly: true})
  40. db, err := bolt.Open(config.IniConf.Section("server").Key("ApiAuthDB").Value(), 0600, nil)
  41. if err != nil {
  42. return nil, err
  43. }
  44. defer db.Close()
  45. if claims, ok := token.Claims.(jwt.MapClaims); ok {
  46. iss, ok := claims["iss"]
  47. if !ok {
  48. return nil, errors.New("Missing iss field")
  49. }
  50. var publicKey []byte
  51. err = db.View(func(tx *bolt.Tx) error {
  52. b := tx.Bucket([]byte("auth_api"))
  53. pKey := b.Get([]byte(iss.(string)))
  54. publicKey = append(publicKey, pKey...)
  55. if publicKey == nil {
  56. return errors.New("can not find encrypt publickey")
  57. }
  58. return nil
  59. })
  60. if err != nil {
  61. return nil, err
  62. }
  63. pubk, _ := jwt.ParseRSAPublicKeyFromPEM(publicKey)
  64. return pubk, nil
  65. }
  66. return nil, nil
  67. })
  68. if err == nil && token.Valid {
  69. //todo check whether authtoken is already genrated and sotored in redis
  70. //or not
  71. var clientId string
  72. claims := token.Claims.(jwt.MapClaims)
  73. if v, ok := claims["clientid"].(string); ok {
  74. clientId = v
  75. } else {
  76. clientId = generateClientId()
  77. }
  78. authToken := GenerateToken(clientId)
  79. authToken.Iss = claims["iss"].(string)
  80. var client *redis.Client = util.GetRedis()
  81. client.Select(server.REDIS_API_AUTH_DB)
  82. tokenBytes, err := json.Marshal(authToken)
  83. if err != nil {
  84. return nil, err
  85. }
  86. strCmd := client.HMSet(server.REDIS_API_AUTH_KEY, clientId, string(tokenBytes))
  87. if err = strCmd.Err(); err != nil {
  88. return nil, err
  89. }
  90. return authToken, nil
  91. }
  92. return nil, err
  93. }
  94. var clientIdMutex = sync.Mutex{}
  95. func generateClientId() string {
  96. clientIdMutex.Lock()
  97. defer clientIdMutex.Unlock()
  98. timestamp := time.Now().UnixNano()
  99. rand.Seed(timestamp)
  100. rnum := rand.Intn(100000)
  101. timeStr := fmt.Sprintf("%v%d", time.Now().UnixNano(), rnum)
  102. dst := md5.Sum([]byte(timeStr))
  103. return hex.EncodeToString(dst[0:])
  104. }