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:]) }