auth_client.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. package auth
  2. import (
  3. "bytes"
  4. "crypto/md5"
  5. "encoding/binary"
  6. "encoding/hex"
  7. "errors"
  8. "fmt"
  9. "net"
  10. "strconv"
  11. "sync"
  12. "time"
  13. "git.qianqiusoft.com/library/glog"
  14. "git.qianqiusoft.com/qianqiusoft/light-apiengine/config"
  15. "git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys"
  16. sysutils "git.qianqiusoft.com/qianqiusoft/light-apiengine/utils"
  17. )
  18. const (
  19. __KEY = "Light#dauth-@*I2"
  20. CMD_NEW = "new"
  21. CMD_REMOVE = "remove"
  22. CMD_PINGPONG = "pg"
  23. CMD_PINGPONG_RESP = "pg_resp"
  24. )
  25. var TCPClient *TcpClient
  26. type authPackage struct {
  27. Cmd string
  28. TokenStr string
  29. Content []byte
  30. }
  31. func (ap *authPackage) toBytes() []byte {
  32. buf := bytes.NewBuffer([]byte{})
  33. b := []byte(ap.Cmd)
  34. buf.Write(uint32ToBytes(len(b)))
  35. buf.Write(b)
  36. buf.Write(uint32ToBytes(len(ap.Content)))
  37. buf.Write(ap.Content)
  38. return buf.Bytes()
  39. }
  40. type TcpClient struct {
  41. conn net.Conn // 连接
  42. pchan chan *authPackage // 包chan
  43. done chan bool // 是否done
  44. exited bool // 退出
  45. verified bool // 验证是否
  46. }
  47. // 创建client
  48. func NewTcpClient() *TcpClient {
  49. c := &TcpClient{
  50. pchan: make(chan *authPackage, 100),
  51. done: make(chan bool),
  52. exited: false,
  53. verified: false,
  54. }
  55. return c
  56. }
  57. // 启动
  58. func (c *TcpClient) Start() {
  59. go func() {
  60. defer func() {
  61. if p := recover(); p != nil {
  62. fmt.Println("ecover", p)
  63. }
  64. if c.conn != nil {
  65. c.conn.Close()
  66. }
  67. c.restart()
  68. }()
  69. var err error = nil
  70. address := config.AppConfig.GetKey("auth_server")
  71. //fmt.Println("auth client start, dial address is", address)
  72. c.conn, err = net.Dial("tcp", address)
  73. if err != nil {
  74. //fmt.Println("Error dialing", err.Error())
  75. return
  76. }
  77. fmt.Println("发送验证")
  78. sendVerify(c.conn) // 发送验证,不需要读取返回值,如果验证错误立刻关掉
  79. fmt.Println("读取验证结果")
  80. vresp, err := readString(c.conn)
  81. if err != nil {
  82. fmt.Println("Error dialing", err.Error())
  83. return
  84. }
  85. if vresp != "ok" {
  86. // 验证失败
  87. fmt.Println("verify is not ok", vresp)
  88. return
  89. }
  90. fmt.Println("验证成功")
  91. c.verified = true
  92. // send
  93. go func() {
  94. for {
  95. select {
  96. case data := <-c.pchan:
  97. glog.Infoln("写入数据")
  98. c.conn.SetWriteDeadline(time.Now().Add(time.Second * 2))
  99. _, err := c.conn.Write(data.toBytes())
  100. if err != nil {
  101. fmt.Println("写入内容错误", err.Error())
  102. return
  103. }
  104. case <-c.done:
  105. glog.Infoln("发送数据done退出")
  106. return
  107. }
  108. }
  109. }()
  110. // receive
  111. for {
  112. cmd, err := readString(c.conn) // 读取命令
  113. if err != nil {
  114. c.done <- true
  115. fmt.Println("读取命令错误", err.Error())
  116. break
  117. }
  118. if cmd == CMD_NEW {
  119. err = c.newHandler()
  120. } else if cmd == CMD_REMOVE {
  121. err = c.removeHandler()
  122. } else if cmd == CMD_PINGPONG_RESP {
  123. } else {
  124. fmt.Println("未知cmd", cmd)
  125. continue
  126. }
  127. if err != nil {
  128. c.done <- true
  129. fmt.Println("处理错误", err.Error())
  130. break
  131. }
  132. }
  133. }()
  134. }
  135. // 停止
  136. func (c *TcpClient) Stop() {
  137. c.exited = true
  138. c.conn.Close()
  139. }
  140. // 检测
  141. func (c *TcpClient) restart() {
  142. if c.exited {
  143. // 已退出则不重启
  144. return
  145. }
  146. go func() {
  147. c.verified = false
  148. c.done = make(chan bool)
  149. c.pchan = make(chan *authPackage, 100)
  150. c.exited = false
  151. time.Sleep(3 * time.Second)
  152. c.Start()
  153. }()
  154. }
  155. // 发送bytes
  156. func (c *TcpClient) Send(cmd string, bytess []byte) {
  157. if !c.verified {
  158. fmt.Println("未认证")
  159. return
  160. }
  161. glog.Infoln("发送指令1", cmd)
  162. c.pchan <- &authPackage{
  163. Cmd: cmd,
  164. Content: bytess,
  165. }
  166. glog.Infoln("发送指令2", cmd)
  167. }
  168. // 发送token
  169. func (c *TcpClient) SendToken(token *entitys.Token) {
  170. // glog.Infoln("发送新建token")
  171. bytess := tokenToBytes(token)
  172. c.Send(CMD_NEW, bytess)
  173. }
  174. // 处理创建
  175. func (c *TcpClient) newHandler() error {
  176. // fmt.Println("处理新建")
  177. bytess, err := readBytes(c.conn)
  178. if err != nil {
  179. fmt.Println("读取token内容错误", err.Error())
  180. return err
  181. }
  182. // 新建
  183. token, err := bytesToToken(bytess)
  184. if err != nil {
  185. glog.Infoln("bytesToToken 错误", err.Error())
  186. return err
  187. }
  188. sysutils.GetGlobalTokenStore().Set(token.AccessToken, token)
  189. return nil
  190. }
  191. // 处理删除
  192. func (c *TcpClient) removeHandler() error {
  193. fmt.Println("处理删除")
  194. bytess, err := readBytes(c.conn)
  195. if err != nil {
  196. fmt.Println("读取token内容错误", err.Error())
  197. return err
  198. }
  199. // 移除,此时bytess为tokenstring
  200. sysutils.GetGlobalTokenStore().Remove(string(bytess))
  201. return nil
  202. }
  203. // 读取字符串
  204. func readString(conn net.Conn) (string, error) {
  205. // 读长度
  206. size, err := readUInt32(conn)
  207. if err != nil {
  208. fmt.Println("读取长度失败,", err.Error())
  209. return "", err
  210. }
  211. // 读字符串
  212. b := make([]byte, size)
  213. n, err := conn.Read(b)
  214. if n != int(size) {
  215. return "", errors.New("读取长度不是" + strconv.Itoa(int(size)))
  216. }
  217. return string(b), nil
  218. }
  219. // 写入字符串
  220. func writeString(conn net.Conn, str string) error {
  221. if str == "" {
  222. return errors.New("字符串为空")
  223. }
  224. bytess := []byte(str)
  225. size := len(bytess)
  226. // 发送长度
  227. err := writeUInt32(conn, uint32(size))
  228. if err != nil {
  229. fmt.Println("发送长度失败,", err.Error())
  230. return err
  231. }
  232. // 发送内容
  233. n, err := conn.Write(bytess)
  234. if err != nil {
  235. fmt.Println("发送内容失败,", err.Error())
  236. return err
  237. }
  238. if n != size {
  239. return errors.New("发送长度不是" + strconv.Itoa(int(size)))
  240. }
  241. return nil
  242. }
  243. // 读取bytes
  244. func readBytes(conn net.Conn) ([]byte, error) {
  245. // 读长度
  246. size, err := readUInt32(conn)
  247. if err != nil {
  248. fmt.Println("读取长度失败,", err.Error())
  249. return nil, err
  250. }
  251. // 读字符串
  252. b := make([]byte, size)
  253. n, err := conn.Read(b)
  254. if n != int(size) {
  255. return nil, errors.New("读取长度不是" + strconv.Itoa(int(size)))
  256. }
  257. return b, nil
  258. }
  259. // 读取uint64
  260. func readUInt32(conn net.Conn) (uint32, error) {
  261. b := make([]byte, 4)
  262. n, err := conn.Read(b)
  263. if err != nil {
  264. fmt.Println("读取长度失败,", err.Error())
  265. return 0, err
  266. }
  267. if n != 4 {
  268. return 0, errors.New("读取长度不是4")
  269. }
  270. size := binary.BigEndian.Uint32(b)
  271. return size, nil
  272. }
  273. // 写入长度
  274. func writeUInt32(conn net.Conn, v uint32) error {
  275. // 发送长度
  276. b := make([]byte, 4)
  277. binary.BigEndian.PutUint32(b, v)
  278. n, err := conn.Write(b)
  279. if err != nil {
  280. fmt.Println("发送长度失败,", err.Error())
  281. return err
  282. }
  283. if n != 4 {
  284. return errors.New("发送长度不是4")
  285. }
  286. return nil
  287. }
  288. // 写入长度
  289. func writeUInt64(conn net.Conn, v uint64) error {
  290. // 发送长度
  291. b := make([]byte, 8)
  292. binary.BigEndian.PutUint64(b, v)
  293. n, err := conn.Write(b)
  294. if err != nil {
  295. fmt.Println("发送长度失败,", err.Error())
  296. return err
  297. }
  298. if n != 4 {
  299. return errors.New("发送长度不是4")
  300. }
  301. return nil
  302. }
  303. // 读取uint64
  304. func readStringByBytes(bytess []byte) (string, int, error) {
  305. size := binary.BigEndian.Uint32(bytess)
  306. return string(bytess[4 : 4+size]), int(size), nil
  307. }
  308. // int转bytes
  309. func uint32ToBytes(v int) []byte {
  310. b := make([]byte, 4)
  311. binary.BigEndian.PutUint32(b, uint32(v))
  312. return b
  313. }
  314. // int转bytes
  315. func uint64ToBytes(v int) []byte {
  316. b := make([]byte, 8)
  317. binary.BigEndian.PutUint32(b, uint32(v))
  318. return b
  319. }
  320. // 转token
  321. func bytesToToken(content []byte) (*entitys.Token, error) {
  322. token := &entitys.Token{Lock: new(sync.RWMutex)}
  323. var index int = 0
  324. var size int
  325. var err error = nil
  326. // fmt.Println("读取userid")
  327. token.UserId, size, err = readStringByBytes(content)
  328. if err != nil {
  329. fmt.Println("读取userid错误")
  330. return nil, err
  331. }
  332. index += 4 + size
  333. // fmt.Println("读取AccessToken")
  334. token.AccessToken, size, err = readStringByBytes(content[index:])
  335. if err != nil {
  336. fmt.Println("读取AccessToken错误")
  337. return nil, err
  338. }
  339. index += 4 + size
  340. // fmt.Println("读取RefreshToken")
  341. token.RefreshToken, size, err = readStringByBytes(content[index:])
  342. if err != nil {
  343. fmt.Println("读取RefreshToken错误")
  344. return nil, err
  345. }
  346. index += 4 + size
  347. // fmt.Println("读取LoginID")
  348. token.LoginID, size, err = readStringByBytes(content[index:])
  349. if err != nil {
  350. fmt.Println("读取LoginID错误")
  351. return nil, err
  352. }
  353. index += 4 + size
  354. // fmt.Println("读取timestamp")
  355. token.TimeStamp = binary.BigEndian.Uint64(content[index:])
  356. index += 8
  357. // fmt.Println("读取ServerIp")
  358. token.ServerIp, size, err = readStringByBytes(content[index:])
  359. if err != nil {
  360. fmt.Println("读取ServerIp错误")
  361. return nil, err
  362. }
  363. index += 4 + size
  364. // fmt.Println("读取Domain")
  365. token.Domain, size, err = readStringByBytes(content[index:])
  366. if err != nil {
  367. fmt.Println("读取Domain错误")
  368. return nil, err
  369. }
  370. index += 4 + size
  371. return token, nil
  372. }
  373. // 转bytes,包括token开头
  374. func tokenToBytes(token *entitys.Token) []byte {
  375. buf := bytes.NewBuffer([]byte{})
  376. t := []byte(token.UserId)
  377. buf.Write(uint32ToBytes(len(t)))
  378. buf.Write(t)
  379. t = []byte(token.AccessToken)
  380. buf.Write(uint32ToBytes(len(t)))
  381. buf.Write(t)
  382. t = []byte(token.RefreshToken)
  383. buf.Write(uint32ToBytes(len(t)))
  384. buf.Write(t)
  385. t = []byte(token.LoginID)
  386. buf.Write(uint32ToBytes(len(t)))
  387. buf.Write(t)
  388. buf.Write(uint64ToBytes(int(token.TimeStamp)))
  389. fmt.Println(token.ServerIp)
  390. t = []byte(token.ServerIp)
  391. buf.Write(uint32ToBytes(len(t)))
  392. buf.Write(t)
  393. fmt.Println(token.Domain)
  394. t = []byte(token.Domain)
  395. buf.Write(uint32ToBytes(len(t)))
  396. buf.Write(t)
  397. bytess := buf.Bytes()
  398. buf = bytes.NewBuffer([]byte{}) // 这里用reset是错误的
  399. tokenstrbytes := []byte(token.AccessToken)
  400. buf.Write(uint32ToBytes(len(tokenstrbytes)))
  401. buf.Write(tokenstrbytes)
  402. buf.Write(uint32ToBytes(len(bytess)))
  403. buf.Write(bytess)
  404. return buf.Bytes()
  405. }
  406. // 发送验证
  407. func sendVerify(conn net.Conn) {
  408. timestamp := time.Now().UnixNano()
  409. timestampStr := strconv.Itoa(int(timestamp))
  410. seed := timestampStr + __KEY
  411. hashVal := hash(seed)
  412. writeUInt64(conn, uint64(timestamp))
  413. writeString(conn, hashVal)
  414. }
  415. // md5 哈希
  416. func hash(str string) string {
  417. h := md5.New()
  418. h.Write([]byte(str))
  419. return hex.EncodeToString(h.Sum(nil))
  420. }