api接口,appkey、appsecret生成

3,561 阅读5分钟

一、什么是appid、appkey、appsecret

AppID:应用的唯一标识
AppKey:公匙(相当于账号)
AppSecret:私匙(相当于密码)

app_id 是用来标记你的开发者账号的, 是你的用户id, 这个id 在数据库添加检索, 方便快速查找。

app_key 和 app_secret 是一对出现的账号, 同一个 app_id 可以对应多个 app_key+app_secret, 这样 平台就可以分配你不一样的权限, 比如 app_key1 + app_secect1 只有只读权限 但是 app_key2+app_secret2 有读写权限… 这样你就可以把对应的权限 放给不同的开发者. 其中权限的配置都是直接跟app_key 做关联的, app_key 也需要添加数据库检索, 方便快速查找。

至于为什么 要有app_key + app_secret 这种成对出现的机制呢, 因为 要加密, 通常 在首次验证(类似登录场景) , 你需要用 app_key(标记要申请的权限有哪些) + app_secret(密码, 表示你真的拥有这个权限) 来申请一个token, 就是我们经常用到的 access_token, 之后的数据请求, 就直接提供access_token 就可以验证权限了。

使用方法:

向第三方服务器请求授权时,带上AppKey和AppSecret(需存在服务器端)

第三方服务器验证AppKey和AppSecret在DB中有无记录

如果有,生成一串唯一的字符串(token令牌),返回给服务器,服务器再返回给客户端

客户端下次请求敏感数据时带上令牌

二、UUID

uuid是指在一台机器在同一时间中生成的数字在所有机器中都是唯一的,按照开放软件基金会(OSF)指定的标准计算,用到了以太网卡的地址、纳秒级时间、芯片ID码和愈多可能的数字。
UUID由以下几部分的组合:
1)当前日期和时间
2)时钟序列
3)全局唯一的IEEE机器识别号,如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。

标准的UUID格式为:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12),以连字号分为五段形式的36个字符

参考:UUID

2.0 golang三方库 "github.com/google/uuid" 中提供了生成uuid的方法

uuidByte, err := uuid.NewUUID() 
uuid := uuidByte.String()
func NewUUID() (UUID, error) {
   var uuid UUID
   now, seq, err := GetTime()
   if err != nil {
      return uuid, err
   }

   timeLow := uint32(now & 0xffffffff)
   timeMid := uint16((now >> 32) & 0xffff)
   timeHi := uint16((now >> 48) & 0x0fff)
   timeHi |= 0x1000 // Version 1

   binary.BigEndian.PutUint32(uuid[0:], timeLow)
   binary.BigEndian.PutUint16(uuid[4:], timeMid)
   binary.BigEndian.PutUint16(uuid[6:], timeHi)
   binary.BigEndian.PutUint16(uuid[8:], seq)

   nodeMu.Lock()
   if nodeID == zeroID {
      setNodeInterface("")
   }
   copy(uuid[10:], nodeID[:])
   nodeMu.Unlock()

   return uuid, nil
}

也可以自己生成uuid:

2.1 crypto/rand

var Reader io.Reader
Reader是一个全局、共享的密码用强随机数生成器。在Unix类型系统中,会从/dev/urandom读取;而Windows中会调用CryptGenRandom API。

import (
   "crypto/rand"
   "encoding/base64"
   "io"
)

//sessionId函数用来生成一个session ID,即session的唯一标识符
func sessionId() string {
   b := make([]byte, 32)
   //ReadFull从rand.Reader精确地读取len(b)字节数据填充进b
   //rand.Reader是一个全局、共享的密码用强随机数生成器
   if _, err := io.ReadFull(rand.Reader, b); err != nil {
      return ""
   }
   fmt.Println(b) // [20 80 171 250 192 24 219 161 117 79 193 253 153 87 197 120 9 170 14 129 143 239 171 1 97 216 168 172 50 18 174 70]
   return base64.URLEncoding.EncodeToString(b)//将生成的随机数b编码后返回字符串,该值则作为session ID
}
func main() {
   fmt.Println(sessionId()) // FFCr-sAY26F1T8H9mVfFeAmqDoGP76sBYdiorDISrkY=
}

参考:go标准库学习 crypto/rand

2.2 Rand UUID

package common

import (
   crand "crypto/rand"
   "encoding/hex"
   "errors"
   "fmt"
   mrand "math/rand"
   "regexp"
   "strings"
   "time"
)

// seeded indicates if math/rand has been seeded
var seeded bool = false

// uuidRegex matches the UUID string
var uuidRegex *regexp.Regexp = regexp.MustCompile(`^{?([a-fA-F0-9]{8})-?([a-fA-F0-9]{4})-?([a-fA-F0-9]{4})-?([a-fA-F0-9]{4})-?([a-fA-F0-9]{12})}?$`)

// UUID type.
type UUID [16]byte

// Hex returns a hex string representation of the UUID in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.
func (this UUID) Hex() string {
   x := [16]byte(this)
   return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
      x[0], x[1], x[2], x[3], x[4],
      x[5], x[6],
      x[7], x[8],
      x[9], x[10], x[11], x[12], x[13], x[14], x[15])
}

// Rand generates a new version 4 UUID.
func Rand() UUID {
   var x [16]byte
   randBytes(x[:])
   x[6] = (x[6] & 0x0F) | 0x40
   x[8] = (x[8] & 0x3F) | 0x80
   return x
}

// FromStr returns a UUID based on a string.
// The string could be in the following format:
//
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
//
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
//
// If the string is not in one of these formats, it'll return an error.
func FromStr(s string) (id UUID, err error) {
   if s == "" {
      err = errors.New("Empty string")
      return
   }

   parts := uuidRegex.FindStringSubmatch(s)
   if parts == nil {
      err = errors.New("Invalid string format")
      return
   }

   var array [16]byte
   slice, _ := hex.DecodeString(strings.Join(parts[1:], ""))
   copy(array[:], slice)
   id = array
   return
}

// randBytes uses crypto random to get random numbers. If fails then it uses math random.
func randBytes(x []byte) {

   length := len(x)
   n, err := crand.Read(x)

   if n != length || err != nil {
      if !seeded {
         mrand.Seed(time.Now().UnixNano())
      }

      for length > 0 {
         length--
         x[length] = byte(mrand.Int31n(256))
      }
   }
}

func main() {

   got := Rand().Hex()
   fmt.Println(got) // 2df597df-b6ac-41d5-92e7-4e1aaba7f4c9
   
   id, _ := FromStr(got)
   fmt.Println(UUID(id)) // [45 245 151 223 182 172 65 213 146 231 78 26 171 167 244 201]
}

三、云服务 AppId或AppKey和AppSecret生成策略

参考:AppKey和AppSecret生成策略

import (
   "crypto/sha1"
   "encoding/hex"
   "github.com/google/uuid"
   "sort"
   "strconv"
   "strings"
   //_uuid "myproject/uuid"
)

const (
   SERVER_NAME = "myproject_abc123"
)

var (
   chars = []string{"a", "b", "c", "d", "e", "f",
      "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
      "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
      "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I",
      "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
      "W", "X", "Y", "Z"}
)

func getAppKey() string {
   // 1.
   uuidByte, err := uuid.NewUUID()
   if err != nil {
      panic("new uuid error")
   }
   uuid := strings.ReplaceAll(uuidByte.String(), "-", "")

   // 2.
   //uuid := _uuid.Rand().Hex()
   //uuid = strings.ReplaceAll(uuid, "-", "")

   appKey := ""
   for i := 0; i < 8; i++ {
      str := uuid[i*4:i*4+4]
      x, _ := strconv.ParseInt(str, 16, 64)
      appKey += chars[x % 0x3e]
   }
   return appKey
}

func getAppSecret(appKey string) string {
   sli := []string{appKey, SERVER_NAME}
   sort.Strings(sli)
   str := strings.Join(sli, "")

   h := sha1.New()
   h.Write([]byte(str))
   return hex.EncodeToString(h.Sum(nil))
}

func main() {
   appKey := getAppKey()
   appSecret := getAppSecret(appKey)
   fmt.Println("appKey",appKey) // EO8bvxGl
   fmt.Println("appSecret",appSecret) // 215bc9d7e1ab16c663289d40cea8164b9b00e307
}