123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- package service
- import (
- "crypto/md5"
- "encoding/base64"
- "encoding/hex"
- "encoding/json"
- "errors"
- "fmt"
- "math/rand"
- "strings"
- "sync"
- "time"
- "github.com/boltdb/bolt"
- "github.com/dgrijalva/jwt-go"
- "github.com/pborman/uuid"
- "gopkg.in/redis.v2"
- "xiaoniaokuaiyan.com/xiaoniao/config"
- server "xiaoniaokuaiyan.com/xiaoniao/server"
- "xiaoniaokuaiyan.com/xiaoniao/util"
- )
- type AuthService struct {
- server.AuthService
- }
- func GenerateToken(clientId string) *server.AuthToken {
- token := uuid.NewRandom()
- tokenStr := strings.TrimRight(base64.URLEncoding.EncodeToString([]byte(token)), "=")
- return &server.AuthToken{
- AccessToken: tokenStr,
- TokenType: "Bearer",
- Expiry: util.Time{time.Now().Add(time.Hour)},
- ClientId: clientId,
- }
- }
- func (auth *AuthService) GetAccessToken(strToken string) (interface{}, error) {
- token, err := jwt.Parse(strToken, func(token *jwt.Token) (interface{}, error) {
- if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
- return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
- }
- //db, err := bolt.Open("auth.db", 0666, &bolt.Options{ReadOnly: true})
- db, err := bolt.Open(config.IniConf.Section("server").Key("ApiAuthDB").Value(), 0600, nil)
- if err != nil {
- return nil, err
- }
- defer db.Close()
- if claims, ok := token.Claims.(jwt.MapClaims); ok {
- iss, ok := claims["iss"]
- if !ok {
- return nil, errors.New("Missing iss field")
- }
- var publicKey []byte
- err = db.View(func(tx *bolt.Tx) error {
- b := tx.Bucket([]byte("auth_api"))
- pKey := b.Get([]byte(iss.(string)))
- publicKey = append(publicKey, pKey...)
- if publicKey == nil {
- return errors.New("can not find encrypt publickey")
- }
- return nil
- })
- if err != nil {
- return nil, err
- }
- pubk, _ := jwt.ParseRSAPublicKeyFromPEM(publicKey)
- return pubk, nil
- }
- return nil, nil
- })
- if err == nil && token.Valid {
- //todo check whether authtoken is already genrated and sotored in redis
- //or not
- var clientId string
- claims := token.Claims.(jwt.MapClaims)
- if v, ok := claims["clientid"].(string); ok {
- clientId = v
- } else {
- clientId = generateClientId()
- }
- authToken := GenerateToken(clientId)
- authToken.Iss = claims["iss"].(string)
- var client *redis.Client = util.GetRedis()
- client.Select(server.REDIS_API_AUTH_DB)
- tokenBytes, err := json.Marshal(authToken)
- if err != nil {
- return nil, err
- }
- strCmd := client.HMSet(server.REDIS_API_AUTH_KEY, clientId, string(tokenBytes))
- if err = strCmd.Err(); err != nil {
- return nil, err
- }
- return authToken, nil
- }
- return nil, err
- }
- var clientIdMutex = sync.Mutex{}
- func generateClientId() string {
- clientIdMutex.Lock()
- defer clientIdMutex.Unlock()
- timestamp := time.Now().UnixNano()
- rand.Seed(timestamp)
- rnum := rand.Intn(100000)
- timeStr := fmt.Sprintf("%v%d", time.Now().UnixNano(), rnum)
- dst := md5.Sum([]byte(timeStr))
- return hex.EncodeToString(dst[0:])
- }
|