Golang 微服务教程(四)
发表于 2018-05-27 | 阅读次数: | 字数统计: 2,953
原文链接:ewanvalentine.io,翻译已获作者 Ewan Valentine 授权。
本文完整代码:GitHub
上节引入 user-service 微服务并在 Postgres 中存储了用户数据,包括明文密码。本节将对密码进行安全的加密处理,并使用唯一的 token 来在各微服务之间识别用户。
在开始之前,需要手动运行数据库容器:
12$ docker run -d -p 5432:5432 postgres$ docker run -d -p 27017:27017 mongo
密码的哈希处理
安全原则
遵循 ”即使发生数据泄露,密码等敏感数据也不能被还原“ 的原则,永远都不要明文存储用户的密码。尽管一直这么说,但仍有项目是明文存储,比如以前的 CSDN
哈希处理
现在更新一下 user-service/handler.go 中处理密码的逻辑,将密码进行哈希处理,再进行存储:
// user-service/hander.gofunc (h *handler) Create(ctx context.Context, req *pb.User, resp *pb.Response) error {// 哈希处理用户输入的密码hashedPwd, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)if err != nil {return err}req.Password = string(hashedPwd)if err := h.repo.Create(req); err != nil {return nil}resp.User = reqreturn nil}func (h *handler) Auth(ctx context.Context, req *pb.User, resp *pb.Token) error {u, err := h.repo.GetByEmailAndPassword(req)if err != nil {return err}// 进行密码验证if err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(req.Password)); err != nil {return err}t, err := h.tokenService.Encode(u)if err != nil {return err}resp.Token = treturn nil}
只在两个函数上有改动:在 Create() 中添加了密码哈希处理的逻辑,在 Auth() 中用密码的哈希值做验证。重新创建用户,密码如下:
现在已经成功结合数据库完成用户的密码验证,在多个微服务之间进行用户验证有很多选择方案,本文使用 JWT
JWT
简介
JWT 是 JSON web tokens 的缩写,是一种类似 OAuth 的分布式安全协议。理解起来很简单,JWT 协议算法能为每个用户生成独特的哈希字符串,并以此来做校验和识别。此外,用户的 metadata(信息数据)也能作为加密字符串的一部分。比如:
1eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
可以看到 token 是被 “.” 分割为三部分的字符串:header.payload.signature
header
JWT 头部包含两部分:声明 token 类型、加密 token 的算法,其进行 base64 加密后作为 token 的第一部分:
{ "typ": "JWT