zoukankan      html  css  js  c++  java
  • reflect反射的实际中的应用及畅想

    https://mojotv.cn/go/create-your-own-ssh-server

    1. 解决了什么

    我有很多行日志数据单行的格式是这样的

    HOST;000012000629948340196501;ipv4;3; ips: user_id=2;user_name=172.21.1.102;policy_id=1;src_mac=52:54:00:62:7f:4a;dst_mac=58:69:6c:7b:fa:e7;src_ip=172.21.1.102;dst_ip=172.22.2.3;src_port=48612;dst_port=80;app_name=网页浏览(HTTP);protocol=TCP;app_protocol=HTTP;event_id=1310909;event_name=Microsoft_IIS_5.1_Frontpage扩展路径信息漏洞;event_type=安全漏洞;level=info;ctime=2019-12-26 11:17:17;action=pass
    

    其中ips: 之前的都是不规范的字段

    我需要把他解析成结构化的数据,这样的

    type IpsItem struct {
    	UserId      int    `json:"user_id"`
    	UserName    string `json:"user_name"`
    	SrcIp       string `json:"src_ip"`
    	DstIp       string `json:"dst_ip"`
    	SrcPort     int    `json:"src_port"`
    	DstPort     int    `json:"dst_port"`
    	AppName     string `json:"app_name"`
    	Protocol    string `json:"protocol"`
    	AppProtocol string `json:"app_protocol"`
    	EventId     int    `json:"event_id"`
    	EventName   string `json:"event_name"`
    	EventType   string `json:"event_type"`
    	Level       string `json:"level"`
    	Ctime       string `json:"ctime"`
    	Action      string `json:"action"`
    }
    

    如果上面日志文件是json就非常容易解决了. 因为golang 标准库使用的就是 reflect反射生成 struct.

    所以我的思路也是使用reflect反射实现字符串转换成结构化的数据,您也可以大致了解标准库json.Unmarshal的原理.

    2. 直接上代码

    package main
    
    import (
    	"fmt"
    	"reflect"
    	"strings"
    )
    
    var testRawString = "HOST;000012000629948340196501;ipv4;3; ips: user_id=2;user_name=172.21.1.102;policy_id=1;src_mac=52:54:00:62:7f:4a;dst_mac=58:69:6c:7b:fa:e7;src_ip=172.21.1.102;dst_ip=172.22.2.3;src_port=48612;dst_port=80;app_name=网页浏览(HTTP);protocol=TCP;app_protocol=HTTP;event_id=1311495;event_name=HTTP_Nikto_WEB漏洞扫描;event_type=安全扫描;level=warning;ctime=2019-12-26 11:17:17;action=pass"
    
    type IpsItem struct {
    	UserId      int    `json:"user_id"`
    	UserName    string `json:"user_name"`
    	SrcIp       string `json:"src_ip"`
    	DstIp       string `json:"dst_ip"`
    	SrcPort     int    `json:"src_port"`
    	DstPort     int    `json:"dst_port"`
    	AppName     string `json:"app_name"`
    	Protocol    string `json:"protocol"`
    	AppProtocol string `json:"app_protocol"`
    	EventId     int    `json:"event_id"`
    	EventName   string `json:"event_name"`
    	EventType   string `json:"event_type"`
    	Level       string `json:"level"`
    	Ctime       string `json:"ctime"`
    	Action      string `json:"action"`
    }
    
    func NewIpsItem(raw string) *IpsItem {
    	//清除非法的字符
    	raw = strings.ReplaceAll(raw, ":", ";")
    
    	ins := IpsItem{}
    	t := reflect.TypeOf(ins)
    	//遍历结构体属性
    	for i := 0; i < t.NumField(); i++ {
    		//获取属性structField
    		sf := t.Field(i)
    		//属性名称
    		fieldName := sf.Name
    		//tag json的值
    		tagName := sf.Tag.Get("json")
    
    		//获取字段值
    		fieldValue := reflect.ValueOf(&ins).Elem().FieldByName(fieldName)
    
    		//属性的值 type
    		switch sf.Type.Name() {
    		case "int":
    			var someInt int64
    			scanValueFromString(raw, tagName, tagName+"=%d", &someInt)
    			//给属性赋值
    			fieldValue.SetInt(someInt)
    			//todo:: 支持更多类型
    		default:
    			var someString string
    			scanValueFromString(raw, tagName, tagName+"=%s", &someString)
    			////给属性赋值
    			fieldValue.SetString(someString)
    		}
    
    	}
    	return &ins
    }
    
    //scanValueFromString 字符串 字段的值
    func scanValueFromString(raw string, tagJsonValue, format string, someV interface{}) {
    	for _, ss := range strings.Split(raw, ";") {
    		ele := strings.TrimSpace(ss)
    		if strings.HasPrefix(ele, tagJsonValue) {
    			fmt.Sscanf(ele, format, someV)
    			//n, err := fmt.Sscanf(ele, format, someV)
    			//fmt.Println(n, err)
    			return
    		}
    	}
    }
    
    func main() {
    	ii := NewIpsItem(testRawString)
    	fmt.Printf("%+v\n", ii)
    }
    

    3. ☘ 抛砖引玉

    • 使用反射开发gorm.model的自动文档工具
    • 开发自己的json/ini/yml/toml等格式的序列化库
    • 开发自己nginx 日志收集库
  • 相关阅读:
    MVC模式-----struts2框架(2)
    MVC模式-----struts2框架
    html的<h>标签
    jsp脚本元素
    LeetCode "Paint House"
    LeetCode "Longest Substring with At Most Two Distinct Characters"
    LeetCode "Graph Valid Tree"
    LeetCode "Shortest Word Distance"
    LeetCode "Verify Preorder Sequence in Binary Search Tree"
    LeetCode "Binary Tree Upside Down"
  • 原文地址:https://www.cnblogs.com/cheyunhua/p/15567185.html
Copyright © 2011-2022 走看看