认真阅读了一下官方提供的API定义文档,发现绝大多数的API请求都必需带上用户鉴权token,是一个非常重要的功能。
学习了一下Token鉴权的概念,并且成功在大项目的开发中应用上了。先水写一篇伴读笔记记录一下Token的概念和应用场景。
基本概念
令牌(Token)是一种API鉴权的常用方式,尤其是在现代的RESTful服务中。在此背景下,token通常是指JSON Web Token(JWT)
或其他类似的结构,但理论上,它可以是任何可以验证用户身份或会话有效性的数据块。
Token的主要作用和特点如下:
- 身份验证:Token通常在用户登录后生成并返回给用户。当用户进行后续请求时,他们会将此token发送回服务器,以证明自己的身份。这允许服务器识别并授权该用户。
- 状态无关:不同于基于session的鉴权(其中服务器需要跟踪活跃的会话),token-based鉴权是无状态的。每个请求都包含了所有必要的信息,使服务器能够知道请求者是谁并对其进行验证。
- 可携带数据:特别是JWT,它可以携带一些数据,如用户ID、角色或其他属性。这使得服务器在不访问数据库的情况下进行某些验证。
- 跨域:Token可以用于跨域身份验证,因为它不依赖于基于cookie的会话。
- 过期机制:Token可以有一个到期时间。例如,一个token可以被设置为1小时后过期,这会要求用户在1小时后重新登录。
- 安全性:Token可以被加密,确保数据的私密性。当使用JWT时,还可以签名以确保数据的完整性。
应用场景举例
在我们的API定义中,用户在登录后会收到一个token。此后,为了访问需要鉴权的端点(如查询用户信息),用户需要将这个token放在请求的Header或者某个特定的参数中发送到服务器。服务器收到请求后,会验证token的有效性(是否被篡改、是否过期等)。只有验证通过的token,对应的请求才会被允许访问受保护的资源。
例如,假设用户登录后收到了一个JWT token。当他们想要查询自己的信息时,他们会发起一个GET请求,并在请求的Authorization头中附带这个token,类似于:
Authorization: Bearer YOUR_JWT_TOKEN
服务器收到请求后,会提取和验证token。如果token有效,服务器会从token中提取用户ID,然后返回与该ID相关的信息。如果token无效或过期,服务器会返回一个错误响应,通常是**401 Unauthorized
**。
代码中的实现
因为现在所有队伍都还在开发阶段,就不直接贴代码了,可以记录一下代码实现的思路。
首先我们需要创建两个函数:生成Token和验证Token。
生成Token
这个函数会在用户登录API的函数中被调用,给登录用户生成一个Token。
首先我们定义一个空的claims
变量,它是一个jwt.StandardClaims{}
类型,来自github.com/golang-jwt/…库。
Claims
这里需要解释一下Claims这个概念。它是一个JSON对象,包含了我们发送请求所需要的声明信息,其中包含了我们的请求主体和额外的元数据。
jwt.StandardClaims
结构体的定义是:
type StandardClaims struct {
Audience string `json:"aud,omitempty"`
ExpiresAt int64 `json:"exp,omitempty"`
Id string `json:"jti,omitempty"`
IssuedAt int64 `json:"iat,omitempty"`
Issuer string `json:"iss,omitempty"`
NotBefore int64 `json:"nbf,omitempty"`
Subject string `json:"sub,omitempty"`
}
他们的含义是:
Audience (aud)
: JWT 的受众,通常是用户的 ID。ExpiresAt (exp)
: 代表什么时候 token 会过期。这是一个 Unix 时间戳。Id (jti)
: token 的唯一身份标识。IssuedAt (iat)
: 代表这个 JWT 何时被创建。Issuer (iss)
: JWT 的发行者。- **
NotBefore (nbf)**:
定义在某个时间之前,该 JWT 不应被接受。 Subject (sub)
: JWT 的主题。
我们的代码中只需要用到ExpiresAt
和Id
。
我们将用户ID和到期时间(比如现在开始24小时)填充给claims。
然后用jwt.NewWithClaims
方法将我们的claims
生成一个Token,然后再用一个事先定义好的秘钥(secret key)对Token签名,就生成了我们要返回给用户的Token了。
解析和验证Token
这个方法将在所有需要验证用户Token的API函数中被调用。它接收一个Token,然后解析验证这个Token,最后返回用户Id。相当于是生成Token函数的反向过程。
验证Token中间件
当我们定义好解析验证Token的函数后,我们可以写一个中间件函数Authentication()
,它的作用是在所有需要Token鉴权的API工作之前,先验证Token的有效性,如果无效,那么我们就不执行API函数(通过c.Abort()
)。API函数接到通知说验证不通过的话,就直接返回一个HTTP 401 Unauthorized
注册中间件
最后我们将Authentication()
函数注册在所有需要用户token鉴权的函数上,就可以了。
总结
这篇文章记录学习Token在API鉴权中的应用的一些知识。Token作为一种常见的鉴权方式,具有身份验证、状态无关、可携带数据、跨域、过期机制和安全性等特点。我们还介绍了Token在API请求中的应用场景,以及如何在代码中实现Token的生成和验证,包括Claims的概念、Token签名和解析、验证Token的中间件函数等。