「Go 工具箱」go-mask:一個對數據脫敏處理的包

大家好,我是漁夫子。

今天給大家推薦一款在輸出中對敏感數據進行脫敏的工作包:go-mask。

那麼,什麼是對敏感數據脫敏呢?就是將敏感信息輸出的時候替換成星號或其他字符。比如手機號碼,身份證信息,姓名等。

go-mask 包還是比較新的,是在兩週前提交的。所以星標只有 71 個。星標雖少,但功能還是很強大的。我們看看 go-mask 都有哪些功能。

特徵

支持的 tags 標籤

go-mask 只提供了有限的幾個 tags。原因是用戶可以根據需要自定義脫敏函數。以下是 go-mask 支持的 tags:

I6xPer

如何使用

對字符串類型脫敏

package main

import (
 "fmt"

 mask "github.com/showa-93/go-mask"
)

func main() {
 maskValue, _ := mask.String(mask.MaskTypeFixed, "Hello World!!")
 fmt.Println(maskValue) //輸出固定的8個脫敏字符: ********
}

對結構體中的 string 類型字段進行脫敏處理。如下:

package main

import (
 "fmt"

 mask "github.com/showa-93/go-mask"
)

func main() {
 value := struct {
  Title string   `mask:"filled"`
  Casts []string `mask:"fixed"`
 }{
  Title: "Catch Me If You Can",
  Casts: []string{
   "Thomas Jeffrey \"Tom\" Hanks",
   "Leonardo Wilhelm DiCaprio",
  },
 }
 
    maskValue, _ := mask.Mask(value)
 fmt.Printf("value:%+v\n", value)
 fmt.Printf("maskValue:%+v\n", maskValue) //脫敏字符輸出符號是:*
    
    masker := mask.NewMasker()
 masker.SetMaskChar("-") //自定義脫敏字符爲 - 

    // 給對應的tag註冊對應的脫敏處理函數
 masker.RegisterMaskStringFunc(mask.MaskTypeFilled, masker.MaskFilledString)
 masker.RegisterMaskStringFunc(mask.MaskTypeFixed, masker.MaskFixedString)

 maskValue2, _ := masker.Mask(value)


 fmt.Printf("maskValue2:%+v\n", maskValue2)
}

輸出結果如下:

value:{Title:Catch Me If You Can Casts:[Thomas Jeffrey "Tom" Hanks Leonardo Wilhelm DiCaprio]}
maskValue:{Title:******************* Casts:[******** ********]}
maskValue2:{Title:------------------- Casts:[-------- --------]}

對 int/float64 類型字段脫敏

對 int/float64 類型的字段一般使用 mask:"randomXXX" 的標籤,表示轉換成從 0 到 XXX 的隨機數。如下:

package main

import (
 "fmt"

 mask "github.com/showa-93/go-mask"
)

func main() {
 {
  maskValue, _ := mask.Int("random100", 10)
  fmt.Println(maskValue)
 }
 {
  maskValue, _ := mask.Float64("random100.2", 12.3)
  fmt.Println(maskValue)
 }

 {
  value := struct {
   Price   int     `mask:"random1000"`
   Percent float64 `mask:"random1.3"`
  }{
   Price:   300,
   Percent: 0.80,
  }
  masker := mask.NewMasker()
  masker.RegisterMaskIntFunc(mask.MaskTypeRandom, masker.MaskRandomInt)
  masker.RegisterMaskFloat64Func(mask.MaskTypeRandom, masker.MaskRandomFloat64)

  maskValue, _ := mask.Mask(value)
  maskValue2, _ := masker.Mask(value)

  fmt.Printf("%+v\n", maskValue)
  fmt.Printf("%+v\n", maskValue2)
 }
}

對應的輸出結果如下:

29
50.45
{Price:917 Percent:0.183}
{Price:733 Percent:0.241}

對 slice 類型脫敏處理

對 slice 類型的處理本質上還是對基礎類型的處理,類似於結構體或對應的 string/int/float64 類型。如下:

package main

import (
 "fmt"

 "github.com/showa-93/go-mask"
)

type Value struct {
 Name string `mask:"filled"`
 Type int    `mask:"random10"`
}

func main() {
 values := []Value{
  {
   Name: "Thomas Jeffrey \"Tom\" Hanks",
   Type: 1,
  },
  {
   Name: "Leonardo Wilhelm DiCaprio",
   Type: 2,
  },
 }
 masker := mask.NewMasker()
 masker.SetMaskChar("+")
 masker.RegisterMaskStringFunc(mask.MaskTypeFilled, masker.MaskFilledString)
 masker.RegisterMaskIntFunc(mask.MaskTypeRandom, masker.MaskRandomInt)

 maskValues, _ := mask.Mask(values)
 maskValues2, _ := masker.Mask(values)

 fmt.Printf("%+v\n", values)
 fmt.Printf("%+v\n", maskValues)
 fmt.Printf("%+v\n", maskValues2)
}

輸出如下:

[{Name:Thomas Jeffrey "Tom" Hanks Type:1} {Name:Leonardo Wilhelm DiCaprio Type:2}]
[{Name:************************** Type:8} {Name:************************* Type:9}]
[{Name:++++++++++++++++++++++++++ Type:4} {Name:+++++++++++++++++++++++++ Type:8}]

對 map 類型進行處理

對 map 類型的處理,是處理的 map 中的 value,對 key 不做處理。如下:

package main

import (
 "fmt"

 "github.com/showa-93/go-mask"
)

type Value struct {
 Name string `mask:"filled"`
 Type int    `mask:"random10"`
}

func main() {
 values := map[string]Value{
  "one": {
   Name: "Thomas Jeffrey \"Tom\" Hanks",
   Type: 1,
  },
  "two": {
   Name: "Leonardo Wilhelm DiCaprio",
   Type: 2,
  },
 }
 masker := mask.NewMasker()
 masker.SetMaskChar("")
 masker.RegisterMaskStringFunc(mask.MaskTypeFilled, masker.MaskFilledString)
 masker.RegisterMaskIntFunc(mask.MaskTypeRandom, masker.MaskRandomInt)

 maskValues, _ := mask.Mask(values)
 maskValues2, _ := masker.Mask(values)

 fmt.Printf("%+v\n", values)
 fmt.Printf("%+v\n", maskValues)
 fmt.Printf("%+v\n", maskValues2)
}

輸出結果如下:

map[one:{Name:Thomas Jeffrey "Tom" Hanks Type:1} two:{Name:Leonardo Wilhelm DiCaprio Type:2}]
map[one:{Name:************************** Type:8} two:{Name:************************* Type:6}]
map[one:{Name: Type:6} two:{Name: Type:2}]

自定義脫敏函數

go-mask 包還支持自定義的脫敏函數的處理。將定義好的函數通過 mask.RegisterMaskStringFunc 函數進行註冊即可。如下,定義了 regexp 標籤和 MaskRegExp 脫敏處理函數:

package main

import (
 "fmt"
 "regexp"
 "strings"

 mask "github.com/showa-93/go-mask"
)

func init() {
 maskTypeRegExp := "regexp"
 mask.RegisterMaskStringFunc(maskTypeRegExp, MaskRegExp)
}

// MaskRegExp is sample to add a custom mask function
func MaskRegExp(arg, value string) (string, error) {
 var (
  reg *regexp.Regexp
  err error
 )
 reg, err = regexp.Compile(arg)
 if err != nil {
  return "", err
 }

 indexes := reg.FindStringSubmatchIndex(value)
 if len(indexes) >= 4 && indexes[2] >= 0 && indexes[3] >= 0 {
  var sb strings.Builder
  sb.WriteString(value[:indexes[2]])
  sb.WriteString(mask.MaskChar())
  sb.WriteString(value[indexes[3]:])
  return sb.String(), nil
 }

 return value, nil
}

func main() {
 mask.SetMaskChar("cat")
 type Hachiware struct {
  Message string `mask:"regexp(gopher)."`
 }

 input := Hachiware{Message: "I love gopher!"}
 got, _ := mask.Mask(input)
 fmt.Printf("%+v\n", input)
 fmt.Printf("%+v\n", got)

 // The Masker initialized with NewMasker does not have
 // any custom masking functions registered, so no masking will occur
 masker := mask.NewMasker()
 got2, _ := masker.Mask(input)
 fmt.Printf("%+v\n", got2)
}

輸出結果:

{Message:I love gopher!}
{Message:I love cat!}
{Message:I love gopher!}

好了,以上就是 go-mask 的主要功能。如果你的業務中有需要脫敏輸出的需求,推薦使用該包。

該包開源地址:https://github.com/showa-93/go-mask

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/KW5o_BvmXDjpC3NKCdrtLg