package utils import ( "context" "fmt" "pro2d/protos/pb" "time" jwt "github.com/dgrijalva/jwt-go" "google.golang.org/grpc/metadata" ) func CreateToken(account *pb.Account) (tokenString string) { token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "iss": "pro2d-app-server", "aud": "pro2d-app-server", "nbf": time.Now().Unix(), "exp": time.Now().Add(time.Hour).Unix(), "sub": "pro2d", "phone": account.Phone, "uid": account.Uid, }) tokenString, err := token.SignedString([]byte(Pro2DTokenSignedString)) if err != nil { panic(err) } return tokenString } func ParseToken(tokenStr string)*pb.Account{ var clientClaims Claims token, err := jwt.ParseWithClaims(tokenStr, &clientClaims, func(token *jwt.Token) (interface{}, error) { if token.Header["alg"] != "HS256" { //panic("ErrInvalidAlgorithm") Sugar.Error("ErrInvalidAlgorithm") return nil, nil } return []byte(Pro2DTokenSignedString), nil }) if err != nil { Sugar.Error("jwt parse error") return nil } if !token.Valid { Sugar.Error("ErrInvalidToken") return nil } return &clientClaims.Account } // Claims defines the struct containing the token claims. type Claims struct { jwt.StandardClaims //phone string `json:"phone"` //uid int64 `json:"uid"` //device string `json:"device"` pb.Account } // 从 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) *pb.Account{ tokenStr, err := getTokenFromContext(ctx) if err != nil { Sugar.Errorf("get token from context error") return nil } return ParseToken(tokenStr) } // AuthToken 自定义认证 客户端使用 type AuthToken struct { Token string } 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 }