auth_client.go 9.7 KB

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