前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于Golang过滤敏感信息的正确姿势

关于Golang过滤敏感信息的正确姿势

作者头像
李海彬
发布2018-07-26 10:51:56
1.7K0
发布2018-07-26 10:51:56
举报

原文作者:ipfans

今天正好看到一篇关于敏感信息过滤的文章,这算做一个interface实际应用的一些举例和应用。

例子中介绍了一种比较常见的使用场景:使用JSON保存数据时的对诸如用户密码等信息进行保护时候应该做的事情。作者以使用JSON格式保存用户账户和密码为例,讲解了使用json.Unmarshaler接口类型过滤敏感信息。

比如,对于保存敏感数据的结构体:

 1type Credentials struct {
 2    Email string `json:”email”`
 3    Password string `json:”password”`
 4}
 5func (co Credentials) MarshalJSON() ([]byte, error) {
 6    type credentials Credentials
 7    cn := credentials(co)
 8    cn.Password = "[REDACTED]"
 9    return json.Marshal((*credentials)(&cn))
10}

通过定义MarshalJSON方法满足json.Unmarshaler接口类型的要求,这样,当使用json.Unmarshal等方法时,就可以规避掉在日志或者JSON接口之类的方法中输出敏感信息Password

文中提及了json.Unmarshaler接口一个方法,但这种方法并不是完全能够解决所有的类型的敏感信息过滤问题。比如在使用调试过程中,开发人员常常使用的fmt/log包,则不能用这种方法解决。

要解决这个问题,则需要使用另外一个值得注意的接口类型,那么就是fmt.Stringer接口类型。该接口类型通常用于如log/fmt之类的包的输出中。

实际上,我个人认为非常合适的方法是,我们可以特定某个特殊类型Sensitivity,对于敏感信息统一采用这个类型予以保护。这样也方便我们后续添加新的保护方式。

看一下这个敏感信息如何过滤:

 1type Sensitivity string
 2func (s Sensitivity) String() string {
 3    return "[SENSITIVE DATA]"
 4}
 5...
 6    request := CreateUserRequest{
 7        Credentials: Credentials{
 8            Email:    "bilbro@theshire.net",
 9            Password: "theonering",
10        },
11    }
12    fmt.Println("request:", request)

输出结果为:

1request: {{bilbro@theshire.net [SENSITIVE DATA]}}

同样的,我们结合第一个方法中的json.Unmarshaler一起使用时,那么就是一个比较完整的敏感信息过滤方案了。

1type Sensitivity string
2func (s Sensitivity) String() string {
3    return "[SENSITIVE DATA]"
4}
5func (s Sensitivity) MarshalJSON() ([]byte, error) {
6    return []byte(`"[SENSITIVE DATA]"`), nil
7}

这种方式也能很好的兼容各种数据库ORM库,保证我们的功能可以正常应用在数据模型等场景上:

sess, _ := mgo.Dial("")
sess.DB("test").C("data").Insert(&request.Credentials)
var c Credentials
sess.DB("test").C("data").Find(bson.M{}).One(&c)
fmt.Println(c.Password == "theonering")
...
db, _ := gorm.Open("mysql", "root:pwd@/ytest?charset=utf8&parseTime=True&loc=Local")
...
db.Create(&request.Credentials)
var c Credentials
db.First(&c)
fmt.Println(c.Password == "theonering")

类似的还有一个涉及编码方法encoding.TextMarshaler,基本与fmt.Stringer类似,因此也不需要额外的赘述了。

注意:如果你使用了如fmt.Sprintf之类的格式化请求,也会受到fmt.Stringer接口类型的影响,请根据使用情况酌情使用。

版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-06-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Golang语言社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档