Explorar o código

调整文件结构;添加authclient;修复logmiddelware 初始化问题

huangrf %!s(int64=5) %!d(string=hai) anos
pai
achega
a0abc60d1c

+ 1 - 1
controllers/partial/SsoController.go

@@ -6,7 +6,7 @@ import (
 	"git.qianqiusoft.com/qianqiusoft/light-apiengine/logs"
 	sysmodel "git.qianqiusoft.com/qianqiusoft/light-apiengine/models"
 	sysutils "git.qianqiusoft.com/qianqiusoft/light-apiengine/utils"
-	"git.qianqiusoft.com/qianqiusoft/light-apiengine/utils/auth"
+	"git.qianqiusoft.com/qianqiusoft/light-apiengine/engine/auth"
 	"strings"
 
 	//"git.qianqiusoft.com/qianqiusoft/light-apiengine/models"

+ 9 - 1
engine/apiengine.go

@@ -2,6 +2,8 @@ package engine
 
 import (
 	"fmt"
+	"time"
+
 	//"github.com/gin-contrib/sessions"
 	//"github.com/gin-contrib/sessions/memstore"
 	//"github.com/gin-contrib/sessions/cookie"
@@ -17,7 +19,7 @@ import (
 	"github.com/gin-gonic/gin"
 	"github.com/xormplus/xorm"
 	"os"
-	"git.qianqiusoft.com/qianqiusoft/light-apiengine/utils/auth"
+	"git.qianqiusoft.com/qianqiusoft/light-apiengine/engine/auth"
 )
 
 type ApiEngine struct {
@@ -139,5 +141,11 @@ func (g *ApiEngine) Run() {
 		ldap := auth.NewLdapAuth(g)
 		go ldap.Init()
 	}
+
+	auth.TCPClient = auth.NewTcpClient()
+	auth.TCPClient.Start()
+
+	time.Sleep(3 * time.Second)
+
 	g.GinEngine.Run(g.Listen_addr)
 }

+ 421 - 0
engine/auth/auth_client.go

@@ -0,0 +1,421 @@
+package auth
+
+import (
+	"bytes"
+	"crypto/md5"
+	"encoding/binary"
+	"encoding/hex"
+	"errors"
+	"fmt"
+	"git.qianqiusoft.com/qianqiusoft/light-apiengine/config"
+	"git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys"
+	sysutils "git.qianqiusoft.com/qianqiusoft/light-apiengine/utils"
+	"net"
+	"strconv"
+	"time"
+)
+
+const (
+	__KEY = "Light#dauth-@*I2"
+
+	CMD_NEW = "new"
+	CMD_REMOVE = "remove"
+)
+
+var TCPClient *TcpClient
+
+type authPackage struct {
+	Cmd string
+	Content []byte
+}
+
+func (ap *authPackage)toBytes()[]byte{
+	buf := bytes.NewBuffer([]byte{})
+
+	b := []byte(ap.Cmd)
+	buf.Write(uint64ToBytes(len(b)))
+	buf.Write(b)
+
+	buf.Write(uint64ToBytes(len(ap.Content)))
+	buf.Write(ap.Content)
+
+	return buf.Bytes()
+}
+
+type TcpClient struct {
+	conn    net.Conn
+	pchan   chan *authPackage
+	done    chan bool
+	exited bool
+	verified   bool
+}
+
+// 创建client
+func NewTcpClient()*TcpClient{
+	c := &TcpClient{
+		pchan: make(chan *authPackage, 100),
+		done:  make(chan bool),
+		exited: false,
+		verified: false,
+	}
+	return c
+}
+
+// 启动
+func(c *TcpClient)Start() {
+	go func() {
+		defer func() {
+			if p := recover(); p != nil {
+				fmt.Println("ecover", p)
+			}
+		}()
+
+		var err error = nil
+		address := config.AppConfig.GetKey("auth_server")
+		fmt.Println("auth client start, dial address is", address)
+		c.conn, err = net.Dial("tcp", address)
+		if err != nil {
+			fmt.Println("Error dialing", err.Error())
+			c.restart()
+			return
+		}
+
+		fmt.Println("发送验证")
+		sendVerify(c.conn) // 发送验证,不需要读取返回值,如果验证错误立刻关掉
+
+		fmt.Println("读取验证结果")
+		vresp, err := readString(c.conn)
+		if err != nil {
+			fmt.Println("Error dialing", err.Error())
+			c.restart()
+			return
+		}
+		if vresp != "ok"{
+			// 验证失败
+			fmt.Println("verify is not ok", vresp)
+			return
+		}
+		c.verified = true
+
+		// send
+		go func() {
+			for {
+				select {
+				case data := <-c.pchan:
+					_, err := c.conn.Write(data.toBytes())
+					if err != nil {
+						fmt.Println("写入内容错误", err.Error())
+						return
+					}
+				case <-c.done:
+					return
+				}
+			}
+		}()
+
+		// receive
+		for {
+			cmd, err := readString(c.conn) // 读取命令
+			if err != nil {
+				c.done <- true
+				fmt.Println("读取命令错误", err.Error())
+				break
+			}
+			bytess, err := readBytes(c.conn)
+			if err != nil {
+				c.done <- true
+				fmt.Println("读取token内容错误", err.Error())
+				break
+			}
+			if cmd == "remove" {
+				// 移除,此时bytess为tokenstring
+				sysutils.GetGlobalTokenStore().Remove(string(bytess))
+			} else if cmd == "new" {
+				// 新建
+				token, _ := bytesToToken(bytess)
+				sysutils.GetGlobalTokenStore().Set(token.AccessToken, token)
+			}
+		}
+
+		c.restart()
+	}()
+}
+
+// 停止
+func(c *TcpClient)Stop(){
+	c.exited = true
+	c.conn.Close()
+}
+
+// 检测
+func(c *TcpClient)restart(){
+	if c.exited{
+		// 已退出则不重启
+		return
+	}
+
+	go func(){
+		time.Sleep(3 * time.Second)
+		c.verified = false
+		c.Start()
+	}()
+}
+
+// 发送bytes
+func(c *TcpClient)Send(cmd string, bytess []byte){
+	if !c.verified{
+		fmt.Println("未认证")
+		return
+	}
+
+	c.pchan <- &authPackage{
+		Cmd: cmd,
+		Content: bytess,
+	}
+}
+
+// 发送token
+func(c *TcpClient)SendToken(token *entitys.Token){
+	c.Send(CMD_NEW, tokenToBytes(token))
+}
+
+// 读取字符串
+func readString(conn net.Conn)(string, error){
+	// 读长度
+	size, err := readUInt32(conn)
+	if err != nil{
+		fmt.Println("读取长度失败,", err.Error())
+		return "", err
+	}
+
+	// 读字符串
+	b := make([]byte, size)
+	n, err := conn.Read(b)
+	if n != int(size){
+		return "", errors.New("读取长度不是" + strconv.Itoa(int(size)))
+	}
+	return string(b), nil
+}
+
+// 写入字符串
+func writeString(conn net.Conn, str string)error{
+	if str == ""{
+		return errors.New("字符串为空")
+	}else{
+		fmt.Println("---->1", str)
+	}
+
+	bytess := []byte(str)
+	size := len(bytess)
+
+	fmt.Println("---->2", str)
+	// 发送长度
+	err := writeUInt32(conn, uint32(size))
+	if err != nil{
+		fmt.Println("发送长度失败,", err.Error())
+		return err
+	}
+
+	fmt.Println("---->3", str)
+	// 发送内容
+	n, err := conn.Write(bytess)
+	if err != nil{
+		fmt.Println("发送内容失败,", err.Error())
+		return err
+	}
+	if n != size{
+		return errors.New("发送长度不是" + strconv.Itoa(int(size)))
+	}
+	fmt.Println("---->4", str)
+
+	return nil
+}
+
+// 读取bytes
+func readBytes(conn net.Conn)([]byte, error){
+	// 读长度
+	size, err := readUInt32(conn)
+	if err != nil{
+		fmt.Println("读取长度失败,", err.Error())
+		return nil, err
+	}
+
+	// 读字符串
+	b := make([]byte, size)
+	n, err := conn.Read(b)
+	if n != int(size){
+		return nil, errors.New("读取长度不是" + strconv.Itoa(int(size)))
+	}
+	return b, nil
+}
+
+// 读取uint64
+func readUInt32(conn net.Conn)(uint32, error){
+	b := make([]byte, 4)
+	n, err := conn.Read(b)
+	if err != nil{
+		fmt.Println("读取长度失败,", err.Error())
+		return 0, err
+	}
+	if n != 4{
+		return 0, errors.New("读取长度不是4")
+	}
+	size := binary.BigEndian.Uint32(b)
+
+	return size, nil
+}
+
+// 写入长度
+func writeUInt32(conn net.Conn, v uint32)error{
+	// 发送长度
+	b := make([]byte, 4)
+	binary.BigEndian.PutUint32(b, v)
+	n, err := conn.Write(b)
+	if err != nil{
+		fmt.Println("发送长度失败,", err.Error())
+		return err
+	}
+	if n != 4{
+		return errors.New("发送长度不是4")
+	}
+
+	return nil
+}
+
+
+// 写入长度
+func writeUInt64(conn net.Conn, v uint64)error{
+	// 发送长度
+	b := make([]byte, 8)
+	binary.BigEndian.PutUint64(b, v)
+	n, err := conn.Write(b)
+	if err != nil{
+		fmt.Println("发送长度失败,", err.Error())
+		return err
+	}
+	if n != 4{
+		return errors.New("发送长度不是4")
+	}
+
+	return nil
+}
+
+
+// 读取uint64
+func readStringByBytes(bytess []byte)(string, int, error) {
+	size := binary.BigEndian.Uint32(bytess)
+	return string(bytess[4 : 4+size]), int(size), nil
+}
+
+// 转token
+func bytesToToken(content []byte)(*entitys.Token, error){
+	token := &entitys.Token{}
+	var index int = 0
+	var size int
+	var err error = nil
+	token.UserId, size, err = readStringByBytes(content)
+	if err != nil{
+		fmt.Println("读取userid错误")
+		return  nil, err
+	}
+	index += 4 + size
+
+	token.AccessToken, size, err = readStringByBytes(content[index:])
+	if err != nil{
+		fmt.Println("读取AccessToken错误")
+		return  nil, err
+	}
+	index += 4 + size
+
+	token.RefreshToken, size, err = readStringByBytes(content[index:])
+	if err != nil{
+		fmt.Println("读取RefreshToken错误")
+		return  nil, err
+	}
+	index += 4 + size
+
+	token.LoginID, size, err = readStringByBytes(content[index:])
+	if err != nil{
+		fmt.Println("读取LoginID错误")
+		return  nil, err
+	}
+	index += 4 + size
+
+	token.TimeStamp = binary.BigEndian.Uint64(content[index:])
+	index += 4
+
+	token.ServerIp, size, err = readStringByBytes(content[index:])
+	if err != nil{
+		fmt.Println("读取ServerIp错误")
+		return  nil, err
+	}
+	index += 4 + size
+
+	token.Domain, size, err = readStringByBytes(content[index:])
+	if err != nil{
+		fmt.Println("读取Domain错误")
+		return  nil, err
+	}
+	index += 4 + size
+
+	return  token, nil
+}
+
+// int转bytes
+func uint64ToBytes(v int)[]byte{
+	b := make([]byte, 4)
+	binary.BigEndian.PutUint32(b, uint32(v))
+
+	return b
+}
+
+// 转bytes
+func tokenToBytes(token *entitys.Token)[]byte{
+	buf := bytes.NewBuffer([]byte{})
+
+	t := []byte(token.UserId)
+	buf.Write(uint64ToBytes(len(t)))
+	buf.Write(t)
+
+	t = []byte(token.AccessToken)
+	buf.Write(uint64ToBytes(len(t)))
+	buf.Write(t)
+
+	t = []byte(token.RefreshToken)
+	buf.Write(uint64ToBytes(len(t)))
+	buf.Write(t)
+
+	t = []byte(token.LoginID)
+	buf.Write(uint64ToBytes(len(t)))
+	buf.Write(t)
+
+	buf.Write(uint64ToBytes(int(token.TimeStamp)))
+
+	t = []byte(token.ServerIp)
+	buf.Write(uint64ToBytes(len(t)))
+	buf.Write(t)
+
+	t = []byte(token.Domain)
+	buf.Write(uint64ToBytes(len(t)))
+	buf.Write(t)
+
+	return buf.Bytes()
+}
+
+// 发送验证
+func sendVerify(conn net.Conn){
+	timestamp := time.Now().UnixNano()
+	timestampStr := strconv.Itoa(int(timestamp))
+	seed := timestampStr + __KEY
+	hashVal := hash(seed)
+
+	writeUInt64(conn, uint64(timestamp))
+	writeString(conn, hashVal)
+}
+
+// md5 哈希
+func hash(str string)string{
+	h := md5.New()
+	h.Write([]byte(str))
+	return hex.EncodeToString(h.Sum(nil))
+}

+ 4 - 41
engine/auth/light_auth.go

@@ -35,53 +35,14 @@ func (la *LightAuth) Login(c *entitys.CtrlContext) {
 			return
 		}
 
-		//token := &entitys.Token{}
-		//timestamp_str := strconv.FormatUint(timestamp, 10)
-		//sec_tooken := sysutils.GenerateToken(logininfo.Account + timestamp_str)
-		//if v := sysutils.GetGlobalTokenStore().Get(sec_tooken); v == nil {
-		//	token.AccessToken = sec_tooken
-		//	token.RefreshToken = sec_tooken
-		//	token.LoginID = logininfo.Account
-		//	token.UserId = user.Id
-		//	token.Result = 200
-		//	//token.Password = pwd
-		//	token.ServerIp = ""
-		//	token.Domain = user.Domain
-		//	sysutils.GetGlobalTokenStore().Set(sec_tooken, token)
-		//	//sysutils.GetGlobalTokenStore().Set(token.LoginID+user.Domain, token)
-		//} else {
-		//	token = v
-		//}
-		//// 查找Business对应的用户信息
-		//var businessUser sysmodel.SysUser
-		//_, err = c.App.GetBusinessDb(user.Domain).Table(new(sysmodel.SysUser)).ID(user.Id).Get(&businessUser)
-		//if err != nil {
-		//	c.Ctx.JSON(200, sysmodel.SysReturn{400, "business db con't found user!", nil})
-		//	return
-		//}
-		//
-		//data := sysmodel.LoginReturnInfo{}
-		//data.Id = user.Id
-		//data.LoginId = user.LoginId
-		//data.Token = token.AccessToken
-		//data.Type = user.Type
-		//data.Domain = user.Domain
-		//data.OrgId = businessUser.OrgId
-		//data.Name = businessUser.Name
-		//data.Mobile = businessUser.Mobile
-		//data.Email = businessUser.Email
-		//
-		//// 查找用户对应角色
-		//var roles []sysmodel.SysRole
-		//c.App.GetBusinessDb(user.Domain).SQL("select sys_role.* from sys_user_role, sys_role where sys_user_role.role_id = sys_role.id and sys_role.del_flag = 0 and sys_user_role.user_id = ? order by sys_role.priority asc", user.Id).Find(&roles)
-		//data.Roles = roles
-
 		data, err := AddToGlobalTokenStore(c, &user)
 		if err != nil {
 			c.Ctx.JSON(200, sysmodel.SysReturn{400, err.Error(), nil})
 			return
 		}
 
+		TCPClient.SendToken(sysutils.GetGlobalTokenStore().Get(data.Token))
+
 		c.Ctx.JSON(200, sysmodel.SysReturn{200, "", data})
 	} else {
 		//fmt.Println(err.Error())
@@ -93,5 +54,7 @@ func (la *LightAuth) Logout(c *entitys.CtrlContext) {
 	token := c.Ctx.GetHeader("token")
 	fmt.Println("delete token: ", token)
 	sysutils.GetGlobalTokenStore().Remove(token)
+
+	TCPClient.Send(CMD_REMOVE, []byte(token))
 	c.Ctx.JSON(200, sysmodel.SysReturn{200, "", nil})
 }

+ 2 - 2
engine/system_init.go

@@ -166,8 +166,8 @@ func initPlatformDbData(db *xorm.Engine) {
 			Id:             "387c50a4-caad-4557-80c8-aca81af9f376",
 			Name:           "日志管理",
 			Parent:         "387c50a4-caad-4557-80c8-aca81af9f370",
-			Url:            "/sys/log",
-			Component:      "system/log",
+			Url:            "/sys/logger",
+			Component:      "system/logger",
 			CreateTime:     models.NowLocal(),
 			LastUpdateTime: time.Now().UnixNano(),
 			OrderNum:       1008,

+ 17 - 13
middleware/logger_cassandra.go

@@ -22,19 +22,23 @@ func init(){
 
 	__logInfoChan = make(chan *logInfo, 1000)
 
-	//// 设置cassandar 配置
-	//_clusterCfg = gocql.NewCluster("218.14.81.38")
-	//_clusterCfg.Keyspace = "i2_log"
-	//_clusterCfg.Consistency = gocql.Quorum
-	////设置连接池的数量,默认是2个(针对每一个host,都建立起NumConns个连接)
-	//_clusterCfg.NumConns = 3
-	//
-	//session, _ := _clusterCfg.CreateSession()
-	//time.Sleep(1 * time.Second) //Sleep so the fillPool can complete.
-	//defer session.Close()
-
-	//// 日志处理
-	//logProcess()
+	// 设置cassandar 配置
+	_clusterCfg = gocql.NewCluster("218.14.81.38")
+	_clusterCfg.Keyspace = "i2_log"
+	_clusterCfg.Consistency = gocql.Quorum
+	//设置连接池的数量,默认是2个(针对每一个host,都建立起NumConns个连接)
+	_clusterCfg.NumConns = 3
+
+	session, err := _clusterCfg.CreateSession()
+	if err != nil{
+		fmt.Println("create session err", err.Error())
+		return
+	}
+	time.Sleep(1 * time.Second) //Sleep so the fillPool can complete.
+	defer session.Close()
+
+	// 日志处理
+	logProcess()
 }
 
 /**