GoでパスワードなどをPrintfで出力させたくない
2016-07-12 / Go
RailsのLoggerだとリクエストパラメータにパスワードなどが含まれていると、FILTERED
といった感じで生の情報が出力されない。
Goでも、例えば、以下のような構造体Userを fmt.Printf("%#v", u)
で出力したときに Password
が隠れて欲しい。
type User struct {
Name string
Password string
}
ノーガード
特に何もしないと、そのまま出力される。
type User struct {
Name string
Password string
}
func main() {
u := &User{
Name: "namae",
Password: "pass",
}
fmt.Printf("%+v", u)
// &{Name:namae Password:pass}
}
[https://play.golang.org/p/HZuuaXwS4O]
そりゃそうだ。
Password を Stringer にしてみる
fmtで出力されるとき、StringerだとStringが呼ばれるはず。
type Password string
func (p Password) String() string {
return "FILTERED"
}
type User struct {
Name string
Password Password
}
func main() {
u := &User{
Name: "namae",
Password: Password("pass"),
}
fmt.Printf("%+v", u)
// &{Name:namae Password:FILTERED}
}
[https://play.golang.org/p/hmNsB0yrbk]
お、できた!?
“%#v” には勝てない
%+v だと出力されないんだけど、%#vだと出力されてしまう…
type Password string
func (p Password) String() string {
return "FILTERED"
}
type User struct {
Name string
Password Password
}
func main() {
u := &User{
Name: "namae",
Password: Password("pass"),
}
fmt.Printf("%#v", u)
// &main.User{Name:"namae", Password:"pass"}
}
[https://play.golang.org/p/1BT9E4dM17]
ポインタ型にしてみる
ポインタ型にしたらどうだろう。
type Password string
func (p Password) String() string {
return "FILTERED"
}
type User struct {
Name string
Password *Password
}
func main() {
p := Password("pass")
u := &User{
Name: "namae",
Password: &p,
}
fmt.Printf("%#v", u)
// &main.User{Name:"namae", Password:(*main.Password)(0x1040a120)}
}
[https://play.golang.org/p/_pcSzrx64p]
アドレスが出力されるので、とりあえずパスワードはわからない状態になった。
まとめ
- とりあえずStringerにする
- 構造体のフィールドとしてはポインタ型にしておく
で良いんだろうか?
もっと良い方法ないだろうか。