auth_client.go 9.7 KB

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