auth_client.go 9.4 KB

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