这是我参与「第五届青训营 」伴学笔记创作活动的第 10 天
这次青训营的大项目需要使用token认证,而且token分布在了两个奇怪的地方,要么是query参数,要么是在form中。而我们最常用的json web token从标准上看应该是放在header中的,而且还要添加Bearer前缀,这也是它另一个名字Bearer Token的由来。
幸运的是,使用echo框架官方维护的jwt包提供了这项功能。
包名是"github.com/labstack/echo-jwt/v4",
命令行里使用这个命令就可以安装了go get -u github.com/labstack/echo-jwt/v4。
jwt里有一个所谓的Claims,在这个包里有提供一个默认的Claims实现,包含jwt必要的一些信息,比如什么时候过期(expiresAt)。其他的信息其实没有什么特别的必要。
我们自己定义的Claims结构体可以包含任何我们想要的信息,比如用户ID,用户名,用户角色等等,并把默认的结构体嵌入进去,这样就可以使用默认的结构体的方法了。
type Claims struct {
jwt.RegisteredClaims
UserID int `json:"user_id"`
Username string `json:"username"`
Role string `json:"role"`
}
签发token的时候,我们需要这个Claims,代码大概像下面这样。
func genToken(username string, id int64, duration time.Duration) *jwt.Token {
// 构造 claims
claims := &customClaims{
username,
id,
jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(duration)),
},
}
// Create token with claims
return jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
}
再之后我们需要提供的密码,加密整个token,生成token字符串。以便于保证安全性。
像是登陆和注册操作就靠这个逻辑签发token,然后把token返回给客户端。
重点在于验证的时候麻烦,客户端实际上没有按照标准的方式给我们传递token,而是把token放在了query参数里,或者是form里。 如果是自己实现的话,就需要纯手动实现查找token了。不过echo框架的jwt为我们解决了这个问题,它可以直接设定中间件的配置,让它从query参数里找token,或者是从form里找token。 具体来说就是它提供了一个lookup字段,只要我们把查找顺序传递进去就可以了。
另外一个便利点在于,它可以让我们在没能验证token时也可以继续执行后续的逻辑,这样我们就提供登陆和不登陆两种方式了。 如果都要自行实现的话,那验证起来还是有些麻烦的,正好有这种库的话,我们就可以贯彻DRY原则了。