agora.io 生成 token 的后端代码没有sdk,只有一个实现。 写的惨不忍睹,单独放到这里以免污染代码。 等到agora做成sdk后替换掉即可。

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