package token import ( "context" "fmt" "time" "github.com/dgrijalva/jwt-go" "google.golang.org/grpc/metadata" ) // 创建token func CreateToken(userName string) (tokenString string) { token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "iss": "grpc-token", "aud": "grpc-token", "nbf": time.Now().Unix(), "exp": time.Now().Add(time.Hour).Unix(), "sub": "user", "username": userName, "timestamp": time.Now().String(), }) //根据key值签名token tokenString, err := token.SignedString([]byte("verysecret")) if err != nil { panic(err) } return tokenString } // AuthTokenn 自定义认证 type AuthToken struct { Token string } // 实现了PerRPCCredentials接口,获取payload func (c AuthToken) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { return map[string]string{ "authorization": c.Token, }, nil } func (c AuthToken) RequireTransportSecurity() bool { return false } // Claims defines the struct containing the token claims. type Claims struct { jwt.StandardClaims // 添加自定义字段 Username string `json:"username"` Timestamp string `json:"timestamp"` } // Step1. 从 context 的 metadata 中,取出 token func getTokenFromContext(ctx context.Context) (string, error) { md, ok := metadata.FromIncomingContext(ctx) if !ok { return "", fmt.Errorf("ErrNoMetadataInContext") } // md 的类型是 type MD map[string][]string token, ok := md["authorization"] if !ok || len(token) == 0 { return "", fmt.Errorf("ErrNoAuthorizationInMetadata") } // 因此,token 是一个字符串数组,只用了 token[0] return token[0], nil } func CheckAuth(ctx context.Context) (username string) { // 从上下文中获取JWT令牌字符串 tokenStr, err := getTokenFromContext(ctx) if err != nil { panic("get token from context error") // 如果获取令牌出错,则抛出错误 } // 定义用于解析JWT令牌的自定义声明结构体 var clientClaims Claims // 解析JWT令牌,并将声明解析到自定义声明结构体中 token, err := jwt.ParseWithClaims(tokenStr, &clientClaims, func(token *jwt.Token) (interface{}, error) { // 检查JWT令牌的算法是否为HS256,如果不是,则抛出错误 if token.Header["alg"] != "HS256" { panic("ErrInvalidAlgorithm") } // 返回用于验证签名的密钥,这里是一个固定的密钥 "verysecret" return []byte("verysecret"), nil }) fmt.Println(token) if err != nil { panic("jwt parse error") // 如果解析JWT出错,则抛出错误 } // 检查JWT令牌是否有效,如果无效,则抛出错误 if !token.Valid { panic("ErrInvalidToken") } // 返回从JWT令牌中提取的用户名 return clientClaims.Username } // 用于验证token func Check(ctx context.Context) bool { // 从上下文中获取JWT令牌字符串 tokenStr, err := getTokenFromContext(ctx) if err != nil { panic("get token from context error") } // 定义用于解析JWT令牌的自定义声明结构体 var clientClaims Claims // 解析JWT令牌,并将声明解析到自定义声明结构体中 token, err := jwt.ParseWithClaims(tokenStr, &clientClaims, func(token *jwt.Token) (interface{}, error) { // 检查JWT令牌的算法是否为HS256,如果不是,则抛出错误 if token.Header["alg"] != "HS256" { panic("ErrInvalidAlgorithm") } // 返回用于验证签名的密钥,这里是一个固定的密钥 "verysecret" return []byte("verysecret"), nil }) fmt.Println(token) if err != nil { return false } // 检查JWT令牌是否有效,如果无效,则抛出错误 if !token.Valid { return false } if clientClaims.Username != "Wuxinyu" { return false } return true }