auth_client.go 9.3 KB

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