这是我参与「第五届青训营 」伴学笔记创作活动的第 16 天
用户模块设计笔记
使用jwt生成和解析token
JSON Web Token(JWT),它定义了一种方式,用于在各方之间安全地将信息作为 JSON 对象传输。由于此信息是经过数字签名的,因此可以被验证和信任。
安装库:
go get -u github.com/dgrijalva/jwt-go@v3.2.0
生成token:
- 首先定义要传输的数据结构体claims,自定义claims使用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"` //主题
}
-
用到两个方法
func jwt.NewWithClaims(method jwt.SigningMethod,claims jwt.Claims)- jwt.SigningMethod中包含三种加密算法:
jwt.SigningMethodHS256, jwt.SigningMethodHS384, jwt.SigningMethodHS512- signedString()方法,返回token
func (*jwt.Token).SignedString(jwtSecret) (string, error)
要求:总体要求三个部分:声明加密的算法+playload主体(传输的数据)+签证(指定密钥(只有服务器知道))
代码:
// GenerateToken 根据username生成一个token
func GenerateToken(username string) string {
u := UserService.GetUserByUsername(new(UserServiceImpl), username)
fmt.Printf("generatetoken: %v\n", u)
token := NewToken(u)
fmt.Printf("签名令牌:", token)
return token
}
// NewToken 根据信息创建token
func NewToken(u dao.TableUser) string {
expiresTime := time.Now().Unix() + int64(config.OneDayOfHours) //过期时间 一天
fmt.Printf("expiresTime: %v\n", expiresTime)
id64 := u.Id
fmt.Printf("id: %v\n", strconv.FormatInt(id64, 10))
claims := jwt.StandardClaims{ //包含的字段 定义需求,也就是通过jwt传输的数据
Audience: u.UserName, //签发人
ExpiresAt: expiresTime, //过期时间
Id: strconv.FormatInt(id64, 10),
IssuedAt: time.Now().Unix(), //签发时间
Issuer: "liuxiang", //签发者
NotBefore: time.Now().Unix(), //生效时间 时间戳 单位s
Subject: "token", //主题
}
if token, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString([]byte("liuxiang") ); err == nil {
println("generate token success!\n")
return token
} else {
println("generate token fail\n")
return "fail"
}
}
解析token
通过解析传入的token字符串,根据StandardClaims结构体定义的相关属性进行校验
Valid方法用于校验鉴权的声明!
func parseToken(token string) (*jwt.StandardClaims, error) {
tokenClaims, err := jwt.ParseWithClaims(token, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, e error) {
return []byte("liuxiang"), nil
})
if err == nil && tokenClaims != nil {
if claim, ok := tokenClaims.Claims.(*jwt.StandardClaims); ok && tokenClaims.Valid {
return claim, nil
}
}
return nil, err
}
密码加密
// 密码加密 md5算法
func EnCoder(password string) string {
p:=[]byte(password)
m:=md5.New()
m.Write(p)
return hex.EncodeToString(m.Sum(nil))
//sum()对hash对象内部存储的内容进行校验,
//追加到data的后面形成一个新的byte切片,
//encoding/hex是一个将byte切片转换为字符串的编码工具库
}
项目启动
注册功能
登录功能
客户端界面
java版实现用户模块
生成并解析token
//生成token
public static String createToken(Long userId, String userName) {
String token = Jwts.builder()
.setSubject("DY-USER")
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
.claim("userId", userId)
.claim("userName", userName)
.signWith(SignatureAlgorithm.HS512, tokenSignKey)
.compressWith(CompressionCodecs.GZIP) //private static final String GZIP = "GZIP";
.compact();
return token;
}
//根据token字符串得到用户id
public static Long getUserId(String token) {
if(StringUtils.isEmpty(token)) return null;
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
Claims claims = claimsJws.getBody();
Long userId = (Long)claims.get("userId");
return userId.longValue();
}
//根据token字符串得到用户名称
public static String getUserName(String token) {
if(StringUtils.isEmpty(token)) return "";
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
Claims claims = claimsJws.getBody();
return (String)claims.get("userName");
}
}