这是我参与「第五届青训营 」伴学笔记创作活动的第 16 天.
token
定义
Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
作用
- 防止表单重复提交
- 用来作身份验证
流程
- 用户首次登录,将输入的账号和密码提交给服务器
- 服务器对输入内容进行校验,若账号和密码匹配则验证通过,登录成功,并生成一个token值,将其保存到数据库,并返回给客户端
- 客户端拿到返回的token值将其保存在本地(如cookie/localStorage),作为公共参数,以后每次请求服务器时都携带该token(放在响应头里),提交给服务器进行校验
- 服务器接收到请求后,首先验证是否携带token,若携带则取出请求头里的token值进行匹配校验,若token值相同则登录成功,且当前正处于登录状态,此时正常返回数据,让app显示数据;若不存在或两个值不一致,则说明原来的登录已经失效,此时返回错误状态码
代码
//生成Token
func (u *User) NewToken() string {
expiresTime := time.Now().Unix() + int64(86400)
//fmt.Printf("expiresTime: %v\n", expiresTime)
id64 := int64(u.Model.ID)
//fmt.Printf("id: %v\n", strconv.FormatInt(id64, 10))
claims := jwt.StandardClaims{
Audience: u.UserName,
ExpiresAt: expiresTime,
Id: strconv.FormatInt(id64, 10),
IssuedAt: time.Now().Unix(),
Issuer: "tiktok",
NotBefore: time.Now().Unix(),
Subject: "token",
}
var jwtSecret = []byte("tiktok")
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
if token, err := tokenClaims.SignedString(jwtSecret); err == nil {
println("generate token success!\n")
return token
} else {
println("generate token fail\n")
return "fail"
}
}
// 对token进行解析
func parseToken(token string) (*jwt.StandardClaims, error) {
jwtToken, err := jwt.ParseWithClaims(token, &jwt.StandardClaims{}, func(token *jwt.Token) (i interface{}, e error) {
return []byte("tiktok"), nil
})
if err == nil && jwtToken != nil {
if claim, ok := jwtToken.Claims.(*jwt.StandardClaims); ok && jwtToken.Valid {
return claim, nil
}
}
return nil, err
}
// 返回id
func (usi *UserServiceImpl) GetparseTokens(token string) (uint, error) {
tokens, err := parseToken(token)
if err != nil {
return 0, err
}
userid, err := strconv.ParseInt(tokens.Id, 10, 64)
if err != nil {
return 0, err
}
return uint(userid), nil
}