Golang 从入门到放弃 -0x18
登录鉴权与 JWT:认证、鉴权、中间件和 token 使用边界。
接口写多了以后,迟早会碰到一个问题:不是所有接口都该让所有人随便调。于是登录、鉴权、权限控制这些东西就来了。很多新手第一次接触时会把“认证”和“鉴权”混成一团,其实这两件事最好分开想。
认证和鉴权不是一回事
- 认证:你是谁
- 鉴权:你能做什么
比如用户登录成功,系统确认“你是 Raymond”,这是认证。接下来判断“你能不能删别人的文章”,这是鉴权。
JWT 是什么
JWT 可以先简单理解成一张签过名的用户票据。服务端生成它,客户端带着它来请求。服务端收到后验证签名,就能知道这张票有没有被篡改,以及里面声明的用户信息。
一个很简化的登录流程
- 用户提交用户名和密码
- 服务端校验通过后生成 JWT
- 客户端把 token 存起来
- 后续请求在 Header 里带上它
签发 token
claims := jwt.MapClaims{
"user_id": 1,
"exp": time.Now().Add(2 * time.Hour).Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString([]byte("secret-key"))这里别把 secret-key 写死在仓库里,这种演示代码放文章里可以,真项目里要从配置里取。
校验 token
func parseToken(tokenString string) (*jwt.Token, error) {
return jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return []byte("secret-key"), nil
})
}解析成功不等于万事大吉,你还得看签名方法、过期时间,以及 claims 里是不是你想要的内容。
常见的 HTTP 中间件写法
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
auth := r.Header.Get("Authorization")
if auth == "" {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
// 省略 token 解析细节
next.ServeHTTP(w, r)
})
}这样一来,挂上这个中间件的接口都会先经过认证检查。
JWT 也不是万能的
很多新手一学 JWT 就容易进入另一个极端,好像有了 JWT 就不用考虑别的了。其实它也有边界:
- token 一旦签发出去,短期内很难强制失效
- claims 里别塞太多敏感信息
- 刷新、注销、黑名单这些问题都还要单独设计
所以不要把 JWT 理解成“安全问题终结者”,它只是认证方案里比较常见的一种实现。
小结
这一章把登录和鉴权先打个底:
- 认证是“你是谁”,鉴权是“你能做什么”。
- JWT 是一种常见票据方案,不是神迹。
- 中间件很适合承接通用认证逻辑。
- 密钥管理、失效策略、权限判断都不能偷懒。
下一章我们讲优雅关闭。服务能启动不稀奇,能不能好好下班,才看得出工程味道。