agora.io 生成 token 的后端代码没有sdk,只有一个实现。 写的惨不忍睹,单独放到这里以免污染代码。 等到agora做成sdk后替换掉即可。 https://docs.agora.io/cn/2.4/product/Interactive%20Broadcast/Agora%20Platform/token

agora.go 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. package agora
  2. import (
  3. "bytes"
  4. "crypto/hmac"
  5. "crypto/sha256"
  6. "encoding/base64"
  7. "encoding/binary"
  8. "encoding/hex"
  9. "fmt"
  10. "hash/crc32"
  11. "io"
  12. "math/rand"
  13. "sort"
  14. "time"
  15. )
  16. // 这里引用了agoda给出的demo,写的并不好,若他们将来有sdk,可以替换成sdk
  17. // Role 角色
  18. type Role uint16
  19. // Roles
  20. const (
  21. Role_Attendee = 1
  22. Role_Publisher = 2
  23. Role_Subscriber = 3
  24. Role_Admin = 4
  25. )
  26. var attendeePrivileges = map[uint16]uint32{
  27. KJoinChannel: 0,
  28. KPublishAudioStream: 0,
  29. KPublishVideoStream: 0,
  30. KPublishDataStream: 0,
  31. }
  32. var publisherPrivileges = map[uint16]uint32{
  33. KJoinChannel: 0,
  34. KPublishAudioStream: 0,
  35. KPublishVideoStream: 0,
  36. KPublishDataStream: 0,
  37. KPublishAudiocdn: 0,
  38. KPublishVideoCdn: 0,
  39. KInvitePublishAudioStream: 0,
  40. KInvitePublishVideoStream: 0,
  41. KInvitePublishDataStream: 0,
  42. }
  43. var subscriberPrivileges = map[uint16]uint32{
  44. KJoinChannel: 0,
  45. KRequestPublishAudioStream: 0,
  46. KRequestPublishVideoStream: 0,
  47. KRequestPublishDataStream: 0,
  48. }
  49. var adminPrivileges = map[uint16]uint32{
  50. KJoinChannel: 0,
  51. KPublishAudioStream: 0,
  52. KPublishVideoStream: 0,
  53. KPublishDataStream: 0,
  54. KAdministrateChannel: 0,
  55. }
  56. // RolePrivileges 角色权限
  57. var RolePrivileges = map[uint16](map[uint16]uint32){
  58. Role_Attendee: attendeePrivileges,
  59. Role_Publisher: publisherPrivileges,
  60. Role_Subscriber: subscriberPrivileges,
  61. Role_Admin: adminPrivileges,
  62. }
  63. // SimpleTokenBuilder
  64. type SimpleTokenBuilder struct {
  65. Token AccessToken
  66. }
  67. func CreateSimpleTokenBuilder(appID, appCertificate, channelName string, uid uint32) SimpleTokenBuilder {
  68. return SimpleTokenBuilder{CreateAccessToken(appID, appCertificate, channelName, uid)}
  69. }
  70. // InitPrivileges expireTimestamp 为0时长期有效
  71. func (builder *SimpleTokenBuilder) InitPrivileges(role Role, expireTimestamp uint32) {
  72. rolepri := uint16(role)
  73. for key, value := range RolePrivileges[rolepri] {
  74. builder.Token.Message[key] = value
  75. }
  76. }
  77. func (builder *SimpleTokenBuilder) InitTokenBuilder(originToken string) bool {
  78. return builder.Token.FromString(originToken)
  79. }
  80. func (builder *SimpleTokenBuilder) SetPrivilege(privilege Privileges, expireTimestamp uint32) {
  81. pri := uint16(privilege)
  82. builder.Token.Message[pri] = expireTimestamp
  83. }
  84. func (builder *SimpleTokenBuilder) RemovePrivilege(privilege Privileges) {
  85. pri := uint16(privilege)
  86. delete(builder.Token.Message, pri)
  87. }
  88. func (builder *SimpleTokenBuilder) BuildToken() (string, error) {
  89. return builder.Token.Build()
  90. }
  91. // 官方的 AccessToken文件
  92. const VERSION_LENGTH = 3
  93. const APP_ID_LENGTH = 32
  94. type Privileges uint16
  95. const (
  96. KJoinChannel = 1
  97. KPublishAudioStream = 2
  98. KPublishVideoStream = 3
  99. KPublishDataStream = 4
  100. KPublishAudiocdn = 5
  101. KPublishVideoCdn = 6
  102. KRequestPublishAudioStream = 7
  103. KRequestPublishVideoStream = 8
  104. KRequestPublishDataStream = 9
  105. KInvitePublishAudioStream = 10
  106. KInvitePublishVideoStream = 11
  107. KInvitePublishDataStream = 12
  108. KAdministrateChannel = 101
  109. )
  110. type AccessToken struct {
  111. AppID string
  112. AppCertificate string
  113. ChannelName string
  114. UidStr string
  115. Ts uint32
  116. Salt uint32
  117. Message map[uint16]uint32
  118. Signature string
  119. CrcChannelName uint32
  120. CrcUid uint32
  121. MsgRawContent string
  122. }
  123. func random(min int, max int) int {
  124. rand.Seed(time.Now().UnixNano())
  125. return rand.Intn(max-min) + min
  126. }
  127. func panichandler() {
  128. if r := recover(); r != nil {
  129. fmt.Println("error: ", r)
  130. }
  131. }
  132. func getVersion() string {
  133. return "006"
  134. }
  135. func CreateAccessToken(appID, appCertificate, channelName string, uid uint32) AccessToken {
  136. var uidStr string
  137. if uid == 0 {
  138. uidStr = ""
  139. } else {
  140. uidStr = fmt.Sprintf("%d", uid)
  141. }
  142. ts := uint32(time.Now().Unix()) + 24*3600
  143. salt := uint32(random(1, 99999999))
  144. message := make(map[uint16]uint32)
  145. return AccessToken{appID, appCertificate, channelName, uidStr, ts, salt, message, "", 0, 0, ""}
  146. }
  147. func (token *AccessToken) FromString(originToken string) bool {
  148. defer panichandler()
  149. dk6version := getVersion()
  150. originVersion := originToken[:VERSION_LENGTH]
  151. if originVersion != dk6version {
  152. return false
  153. }
  154. //originAppID := originToken[VERSION_LENGTH:(VERSION_LENGTH + APP_ID_LENGTH)]
  155. originContent := originToken[(VERSION_LENGTH + APP_ID_LENGTH):]
  156. originContentDecoded, err := base64.StdEncoding.DecodeString(originContent)
  157. if err != nil {
  158. return false
  159. }
  160. signature_, crc_channel_name_, crc_uid_, msg_raw_content_, err := unPackContent(originContentDecoded)
  161. if err != nil {
  162. return false
  163. }
  164. token.Signature = signature_
  165. token.CrcChannelName = crc_channel_name_
  166. token.CrcUid = crc_uid_
  167. token.MsgRawContent = msg_raw_content_
  168. salt_, ts_, messages_, err := unPackMessages(token.MsgRawContent)
  169. if err != nil {
  170. return false
  171. }
  172. token.Salt = salt_
  173. token.Ts = ts_
  174. token.Message = messages_
  175. return true
  176. }
  177. func (token *AccessToken) AddPrivilege(privilege Privileges, expireTimestamp uint32) {
  178. pri := uint16(privilege)
  179. token.Message[pri] = expireTimestamp
  180. }
  181. func (token *AccessToken) Build() (string, error) {
  182. ret := ""
  183. version := getVersion()
  184. buf_m := new(bytes.Buffer)
  185. if err := packUint32(buf_m, token.Salt); err != nil {
  186. return ret, err
  187. }
  188. if err := packUint32(buf_m, token.Ts); err != nil {
  189. return ret, err
  190. }
  191. if err := packMapUint32(buf_m, token.Message); err != nil {
  192. return ret, err
  193. }
  194. bytes_m := buf_m.Bytes()
  195. buf_val := new(bytes.Buffer)
  196. val := token.AppID + token.ChannelName + token.UidStr
  197. buf_val.Write([]byte(val))
  198. buf_val.Write(bytes_m)
  199. bytes_val := buf_val.Bytes()
  200. buf_sig := hmac.New(sha256.New, []byte(token.AppCertificate))
  201. buf_sig.Write(bytes_val)
  202. bytes_sig := buf_sig.Sum(nil)
  203. crc32q := crc32.MakeTable(0xedb88320)
  204. crc_channel_name := crc32.Checksum([]byte(token.ChannelName), crc32q)
  205. crc_uid := crc32.Checksum([]byte(token.UidStr), crc32q)
  206. buf_content := new(bytes.Buffer)
  207. if err := packString(buf_content, string(bytes_sig[:])); err != nil {
  208. return ret, err
  209. }
  210. if err := packUint32(buf_content, crc_channel_name); err != nil {
  211. return ret, err
  212. }
  213. if err := packUint32(buf_content, crc_uid); err != nil {
  214. return ret, err
  215. }
  216. if err := packString(buf_content, string(bytes_m[:])); err != nil {
  217. return ret, err
  218. }
  219. bytes_content := buf_content.Bytes()
  220. ret = version + token.AppID + base64.StdEncoding.EncodeToString(bytes_content)
  221. return ret, nil
  222. }
  223. func packUint16(w io.Writer, n uint16) error {
  224. return binary.Write(w, binary.LittleEndian, n)
  225. }
  226. func packUint32(w io.Writer, n uint32) error {
  227. return binary.Write(w, binary.LittleEndian, n)
  228. }
  229. func packString(w io.Writer, s string) error {
  230. err := packUint16(w, uint16(len(s)))
  231. if err != nil {
  232. return err
  233. }
  234. _, err = w.Write([]byte(s))
  235. return err
  236. }
  237. func packHexString(w io.Writer, s string) error {
  238. b, err := hex.DecodeString(s)
  239. if err != nil {
  240. return err
  241. }
  242. return packString(w, string(b))
  243. }
  244. func packExtra(w io.Writer, extra map[uint16]string) error {
  245. keys := []int{}
  246. if err := packUint16(w, uint16(len(extra))); err != nil {
  247. return err
  248. }
  249. for k := range extra {
  250. keys = append(keys, int(k))
  251. }
  252. //should sorted keys
  253. sort.Ints(keys)
  254. for _, k := range keys {
  255. v := extra[uint16(k)]
  256. if err := packUint16(w, uint16(k)); err != nil {
  257. return err
  258. }
  259. if err := packString(w, v); err != nil {
  260. return err
  261. }
  262. }
  263. return nil
  264. }
  265. func packMapUint32(w io.Writer, extra map[uint16]uint32) error {
  266. keys := []int{}
  267. if err := packUint16(w, uint16(len(extra))); err != nil {
  268. return err
  269. }
  270. for k := range extra {
  271. keys = append(keys, int(k))
  272. }
  273. //should sorted keys
  274. sort.Ints(keys)
  275. for _, k := range keys {
  276. v := extra[uint16(k)]
  277. if err := packUint16(w, uint16(k)); err != nil {
  278. return err
  279. }
  280. if err := packUint32(w, v); err != nil {
  281. return err
  282. }
  283. }
  284. return nil
  285. }
  286. func unPackUint16(r io.Reader) (uint16, error) {
  287. var n uint16
  288. err := binary.Read(r, binary.LittleEndian, &n)
  289. return n, err
  290. }
  291. func unPackUint32(r io.Reader) (uint32, error) {
  292. var n uint32
  293. err := binary.Read(r, binary.LittleEndian, &n)
  294. return n, err
  295. }
  296. func unPackString(r io.Reader) (string, error) {
  297. n, err := unPackUint16(r)
  298. if err != nil {
  299. return "", err
  300. }
  301. buf := make([]byte, n)
  302. r.Read(buf)
  303. s := string(buf[:])
  304. return s, err
  305. }
  306. func unPackContent(buff []byte) (string, uint32, uint32, string, error) {
  307. in := bytes.NewReader(buff)
  308. sig, err := unPackString(in)
  309. if err != nil {
  310. return "", 0, 0, "", err
  311. }
  312. crc_channel_name, err := unPackUint32(in)
  313. if err != nil {
  314. return "", 0, 0, "", err
  315. }
  316. crc_uid, err := unPackUint32(in)
  317. if err != nil {
  318. return "", 0, 0, "", err
  319. }
  320. m, err := unPackString(in)
  321. if err != nil {
  322. return "", 0, 0, "", err
  323. }
  324. return sig, crc_channel_name, crc_uid, m, nil
  325. }
  326. func unPackMessages(msg_str string) (uint32, uint32, map[uint16]uint32, error) {
  327. msg_map := make(map[uint16]uint32)
  328. msg_byte := []byte(msg_str)
  329. in := bytes.NewReader(msg_byte)
  330. salt, err := unPackUint32(in)
  331. if err != nil {
  332. return 0, 0, msg_map, err
  333. }
  334. ts, err := unPackUint32(in)
  335. if err != nil {
  336. return 0, 0, msg_map, err
  337. }
  338. len, err := unPackUint16(in)
  339. if err != nil {
  340. return 0, 0, msg_map, err
  341. }
  342. for i := uint16(0); i < len; i++ {
  343. key, err := unPackUint16(in)
  344. if err != nil {
  345. return 0, 0, msg_map, err
  346. }
  347. value, err := unPackUint32(in)
  348. if err != nil {
  349. return 0, 0, msg_map, err
  350. }
  351. msg_map[key] = value
  352. }
  353. return salt, ts, msg_map, nil
  354. }