sample_chain/peer/token/authtoken.go

145 lines
3.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}