抖音用户模块设计 | 青训营笔记

119 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 16 天

用户模块设计笔记

使用jwt生成和解析token

JSON Web Token(JWT),它定义了一种方式,用于在各方之间安全地将信息作为 JSON 对象传输。由于此信息是经过数字签名的,因此可以被验证和信任。

安装库:

go get -u github.com/dgrijalva/jwt-go@v3.2.0

生成token:

  1. 首先定义要传输的数据结构体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"` //主题
}
  1. 用到两个方法

    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切片转换为字符串的编码工具库
}

项目启动

image-20230221151836173.png

注册功能

image-20230221152443284.png

登录功能

image-20230221152225459.png

客户端界面

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");
    }
}