2017-09-26 112 views
2

省略JSON屬性我有一個用戶結構,它具有像密碼敏感字段:golang - 優雅的方式被序列化

type User struct { 
    UID string `json:"uid" binding:"required"` 
    Password string `json:"password" binding:"required"` 
    EmailAddress string `json:"email" binding:"required"` 
} 

現在我希望能夠利用這個結構來註冊用戶和更新,刪除,但也可以查看。我不想要的是將密碼序列化以供查看。當然,我可以做一個自定義編組,但這是唯一的方法嗎?我嘗試使用json:"-"選項,但這會導致它在解組時被忽略,這是我不想要的。有沒有更好的辦法?

編輯: 爲了讓你們中的一些人放心,我當然不會以明文存儲密碼。這是密碼的bcrypt散列,但仍然如此。我不希望它在我搜索用戶時返回。

+4

或者你可以使用2個結構體,一個帶有「公共」信息和另一個嵌入公共的「完整」版本,並添加諸如密碼之類的「私人」信息。在查看時,只發送/序列化嵌入式公共結構。例如,請參閱相關問題:[使用另一個結構賦值結構](https://stackoverflow.com/questions/31981592/assign-struct-with-another-struct/31981736#31981736)。 – icza

+2

哦,這可能是最接近你的「優雅」,尤其是現在你可以用不同的標籤來轉換相同的結構。我仍然會在「自定義編組器」下標記它,但它比「JSONMarshaler」實現更簡單。 – JimB

回答

3

我想說實施json.Marshaler是,如果你想自定義編組的優雅的解決方案。這是在這種情況下很簡單:

func (u User) MarshalJSON() ([]byte, error) { 
    type user User // prevent recursion 
    x := user(u) 
    x.Password = "" 
    return json.Marshal(x) 
} 

添加「omitempty」在你的用戶類型,如果你不想要的密碼字段編組時,在所有。

+0

我想你是對的。沒有任何進展。我嘗試了不同的方式,但在優雅方面,只有這一點。 – ystark

3

簡單的解決辦法是編組前消毒的用戶結構:

type User struct { 
    UID   string `json:"uid" binding:"required"` 
    Password  string `json:"password,omitempty" binding:"required"` 
    EmailAddress string `json:"email" binding:"required"` 
} 

func sanitizeUser(u User) User { 
    return User{u.UID, "", u.EmailAddress} 
} 

演示:https://play.golang.org/p/RjKVoFc9o8

1

現在我想能夠使用這個結構來註冊一個用戶和更新,刪除,但也可以查看。

另一種解決方案是不在結構中存儲密碼。您不需要查看,刪除或更新(通常)。

您需要它來創建用戶記錄,此時您將在數據存儲中存儲散列。

您需要它來驗證他們的身份(登錄時),在此時您可以驗證數據存儲中的哈希值,然後通常會發出令牌,以便他們繼續訪問該服務。

所以只有幾點你需要它,在這些點你可以簡單地將它保存在內存中並驗證身份,它不需要暴露或存儲在結構中以用於大多數操作。這比國際海事組織更優雅,因爲它在結構中可以非常容易地在導出或日誌記錄中出錯。

+1

這是一個很好的觀點。要解析json文檔中的密碼,您可以簡單地解組兩次。一旦進入你的用戶結構(它沒有密碼字段),然後再進入另一個只有密碼字段的結構。如果這是有道理的。 – Peter

3

我會去與另一個結構和組成。

密碼永遠不應以純文本格式存儲,它們應該安全地散列(bcrypt,pbkdf2等)。該散列是必須被存儲並且不應該被序列化的散列。通過使用組成,你可以做這樣的事情:

type User struct { 
    UID string `json:"uid" binding:"required"` 
    HashedPassword string `json:"-"` 
    EmailAddress string `json:"email" binding:"required"` 
} 

type UserFormData struct { 
    User 
    Password string `json:"password" binding:"required"` 
} 

這也給你更多的靈活性。舉例來說,如果你問用戶確認密碼,你可以簡單地改變UserFormData結構是這樣的:

type UserFormData struct { 
    User 
    Password string `json:"password" binding:"required"` 
    ConfirmPassword string `json:"confirm_password" binding:"required"` 
} 

其中也有優勢,讓您的用戶對象之外的序列化的詳細信息。