这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
part1 什么是用户鉴权
用户鉴权,一种用于在通信网络中对试图访问来自服务提供商的服务的用户进行鉴权的方法。用于用户登陆到DSMP或使用数据业务时,业务网关或Portal发送此消息到DSMP,对该用户使用数据业务的合法性和有效性(状态是否为激活)进行检查。
part2 为什么要使用token用户鉴权
为什么要鉴权:对用户进行鉴权,防止非法用户占用网络资源,非法用户接入网络,被骗取关键信息。
token的优势:传统验证用户身份的方式,大多为基于服务器验证的方式,即cookie+session的方式,由于HTTP协议是无状态的,导致程序需要验证每一次请求,从而辨别客户端的身份,用户登录成功将其信息存入session中,用户每次请求都会将携带session id的cookie一起发送器服务端,进行校验,随着Web、应用程序、以及移动端的崛起,这种验证方式弊端逐渐显现,尤其是在可扩展性方面。引发的问题比如用户增多导致内存开销较大、CORS(跨域资源共享)以及CSRF(跨站请求伪造)等。
引入Token验证机制后,请求会发送token而不再是发送cookie能有效够防止CSRF,即使在客户端使用cookie存储token,但cookie也只有存储功能,而不再具备验证功能,因此安全性得到了极大的提高,而且只要token设计的足够复杂,除非用户泄露,否则几乎没有被破解的可能,加上token是有时效的,在有限的时间加上有限的算力,更是无懈可击,这也类似于加密资产比如比特币钱包对应的私钥,安全性极高。
另外Token可以有效减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。
part3 如何实现用户鉴权
采用方法:Json Web Token 模式(jwt)
鉴权过程详解
2.1、用户发起登陆,客户端提交用户名和密码,服务端会对用户提交的数据进行校验,校验通过以后此时会提取用户关键信息(比如用户名密码、用户id、时间戳等信息进行排序、然后再进行签名运算)通过特定的算法生成token,然后将这个token放在响应头里面返回给客户端。
2.2、客户端收到响应结果,然后会从响应结果里面获取token(这个步骤前端工程师完成),然后将token放在请求头token字段中(通常情况下是这个字段,具体由后端决定),再去请求其他接口。
2.3、服务端再次收到客户端,此时服务端会去请求头中取出token,然后对token进行解签,获取到用户关键信息,再去数据库去进行查询是否存在该用户。但凡这个token被修改过,解签就会失败,鉴权就自然失败了。
2.4、服务端鉴权成功就会返回对应接口数据给客户端,鉴权失败就不会返回对应数据。
GO语言代码实现:
package jwt
import (
"time"
allerrors "github.com/808-not-found/tik_duck/pkg/allerrors"
jwt "github.com/dgrijalva/jwt-go"
)
const TokenExpireDuration = JWTOverTime
var MySecret = []byte(JWTSecret)
// 生成jwt //目前是只进行记录用户名.
func GenToken(username string) (string, error) {
c := MyClaims{
username,
jwt.StandardClaims{
ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(),
Issuer: "xxxxxx",
},
}
// 使用指定的签名方法创建签名对象
token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
// 使用指定的secret签名并获得完成的编码后的字符串token
return token.SignedString(MySecret)
}
// 解析JWT.
func ParseToken(tokenString string) (*MyClaims, error) {
// 解析token
token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (i any, err error) {
return MySecret, nil
})
if err != nil {
return nil, err
}
if claims, ok := token.Claims.(*MyClaims); ok && token.Valid {
return claims, nil
}
return nil, allerrors.ErrJWTParseTokenRun()
}
其中的
JWTSecret 是一个字符串需要自行设定
JWTOverTime 是超时时间 token将会在这么长时间之后失效
type MyClaims struct {
Username string `json:"username"`
jwt.StandardClaims
}
参考资料:
http://testingpai.com/article/1621929988356
https://juejin.cn/post/7003147063542153224
https://www.panziye.com/java/1347.html
码风略丑 读者见谅 --2023/1/24