use token instead of using tls cert
This commit is contained in:
parent
2e1c6a2498
commit
53b4b70ed7
74
README.md
74
README.md
|
@ -1,74 +0,0 @@
|
|||
# FlashChain
|
||||
## 1、需求
|
||||
运行FlashChain,你至少需要golang (version >= 1.19).
|
||||
## 2、如何去使用
|
||||
### 运行代码
|
||||
`go run main.go`
|
||||
## 3、修改配置文件
|
||||
### 配置文件地址(config--config.yaml).
|
||||
```yml
|
||||
block:
|
||||
# 区块大小
|
||||
blksize: 50
|
||||
# 区块的生成时间(单位ms)
|
||||
createBlockTime: 300
|
||||
# 是否查看状态数据库
|
||||
showStateDB: true
|
||||
# 是否查看区块链账本数据库
|
||||
showBlockchainDB: true
|
||||
|
||||
config:
|
||||
# 地址数量
|
||||
addrNum: 1000
|
||||
# 发送的事务数量
|
||||
txNum: 1000
|
||||
# 发送事务时的偏斜度
|
||||
skewness: 1
|
||||
# 发送事务的读占比
|
||||
ratio: 0.5
|
||||
# 是否限制发送速率
|
||||
isLimited: false
|
||||
# 发送速率(单位:个/每秒)
|
||||
rate: 35000
|
||||
# 合约名(目前只支持 SmallBank 和 KvStore 两个合约)
|
||||
contractName: "SmallBank"
|
||||
|
||||
organizations:
|
||||
- name: org1
|
||||
ports:
|
||||
- ":1308"
|
||||
|
||||
client:
|
||||
MSPID: "*.lkq.com"
|
||||
IdentityPath: "cert/client.pem"
|
||||
KeyPath: "cert/client.key"
|
||||
|
||||
peer:
|
||||
address: ":1308"
|
||||
MSPID: "*.lkq.com"
|
||||
IdentityPath: "cert/peer.pem"
|
||||
KeyPath: "cert/peer.key"
|
||||
|
||||
order:
|
||||
address: ":1309"
|
||||
MSPID: "*.lkq.com"
|
||||
IdentityPath: "cert/order.pem"
|
||||
KeyPath: "cert/order.key"
|
||||
|
||||
ca:
|
||||
crt: "cert/ca.crt"
|
||||
```
|
||||
## 4、证明满足原子性和一致性
|
||||
打开main.go中用于测试事务的原子性的代码
|
||||
```golang
|
||||
// 将以下代码注释打开
|
||||
//from := source.Intn(int(config.AddrNum))
|
||||
//to := source.Intn(int(config.AddrNum))
|
||||
//args = [][]byte{
|
||||
// []byte("sendPayment"),
|
||||
// []byte(fmt.Sprintf("%x", from)),
|
||||
// []byte(fmt.Sprintf("%x", to)),
|
||||
// []byte("10"),
|
||||
//}
|
||||
```
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1 +1 @@
|
|||
MANIFEST-000000
|
||||
MANIFEST-000026
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
MANIFEST-000023
|
113
blockDB_1408/LOG
113
blockDB_1408/LOG
|
@ -6,3 +6,116 @@
|
|||
20:19:40.896273 db@open done T·6.1627ms
|
||||
20:19:41.776608 db@close closing
|
||||
20:19:41.777120 db@close done T·512.1µs
|
||||
=============== Apr 18, 2024 (CST) ===============
|
||||
22:03:00.561989 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
|
||||
22:03:00.562985 version@stat F·[] S·0B[] Sc·[]
|
||||
22:03:00.562985 db@open opening
|
||||
22:03:00.562985 journal@recovery F·1
|
||||
22:03:00.563982 journal@recovery recovering @1
|
||||
22:03:00.569048 memdb@flush created L0@2 N·10 S·73KiB "blo..\x11\x17\xd6,v10":"blo..n\x01\x04,v9"
|
||||
22:03:00.570044 version@stat F·[1] S·73KiB[73KiB] Sc·[0.25]
|
||||
22:03:00.581352 db@janitor F·3 G·0
|
||||
22:03:00.581352 db@open done T·18.3669ms
|
||||
22:03:01.313892 db@close closing
|
||||
22:03:01.313892 db@close done T·0s
|
||||
=============== Apr 18, 2024 (CST) ===============
|
||||
22:03:43.483566 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
|
||||
22:03:43.484562 version@stat F·[1] S·73KiB[73KiB] Sc·[0.25]
|
||||
22:03:43.484562 db@open opening
|
||||
22:03:43.485558 journal@recovery F·1
|
||||
22:03:43.485558 journal@recovery recovering @3
|
||||
22:03:43.489545 memdb@flush created L0@5 N·20 S·69KiB "blo..\x11\x17\xd6,d12":"blo..n\x01\x04,d21"
|
||||
22:03:43.490542 version@stat F·[2] S·143KiB[143KiB] Sc·[0.50]
|
||||
22:03:43.502502 db@janitor F·4 G·0
|
||||
22:03:43.502502 db@open done T·17.9395ms
|
||||
22:03:43.586702 db@close closing
|
||||
22:03:43.586702 db@close done T·0s
|
||||
=============== Apr 22, 2024 (CST) ===============
|
||||
15:33:20.698996 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
|
||||
15:33:20.698996 version@stat F·[2] S·143KiB[143KiB] Sc·[0.50]
|
||||
15:33:20.698996 db@open opening
|
||||
15:33:20.699993 journal@recovery F·1
|
||||
15:33:20.699993 journal@recovery recovering @6
|
||||
15:33:20.709958 memdb@flush created L0@8 N·18 S·63KiB "blo..\xb6\x9eg,d33":"blo..n\x01\x04,d42"
|
||||
15:33:20.711963 version@stat F·[3] S·206KiB[206KiB] Sc·[0.75]
|
||||
15:33:20.727650 db@janitor F·5 G·0
|
||||
15:33:20.727650 db@open done T·28.6542ms
|
||||
15:33:21.553041 db@close closing
|
||||
15:33:21.553041 db@close done T·0s
|
||||
=============== Apr 24, 2024 (CST) ===============
|
||||
16:48:03.414524 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
|
||||
16:48:03.415562 version@stat F·[3] S·206KiB[206KiB] Sc·[0.75]
|
||||
16:48:03.415562 db@open opening
|
||||
16:48:03.415562 journal@recovery F·1
|
||||
16:48:03.418338 journal@recovery recovering @9
|
||||
16:48:03.424210 memdb@flush created L0@11 N·16 S·67KiB "blo..-&\x8f,v65":"blo..n\x01\x03,d59"
|
||||
16:48:03.424777 version@stat F·[4] S·274KiB[274KiB] Sc·[1.00]
|
||||
16:48:03.439725 db@janitor F·6 G·0
|
||||
16:48:03.439725 db@open done T·24.1639ms
|
||||
16:48:03.439725 table@compaction L0·4 -> L1·0 S·274KiB Q·68
|
||||
16:48:03.447363 table@build created L1@14 N·8 S·66KiB "blo..-&\x8f,v65":"blo..n\x01\x03,v66"
|
||||
16:48:03.447363 version@stat F·[0 1] S·66KiB[0B 66KiB] Sc·[0.00 0.00]
|
||||
16:48:03.453340 table@compaction committed F-3 S-207KiB Ke·0 D·56 T·13.6142ms
|
||||
16:48:03.453845 table@remove removed @11
|
||||
16:48:03.453845 table@remove removed @8
|
||||
16:48:03.454850 table@remove removed @5
|
||||
16:48:03.454976 table@remove removed @2
|
||||
16:48:04.364509 db@close closing
|
||||
16:48:04.364509 db@close done T·0s
|
||||
=============== Apr 24, 2024 (CST) ===============
|
||||
16:53:40.438835 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
|
||||
16:53:40.439835 version@stat F·[0 1] S·66KiB[0B 66KiB] Sc·[0.00 0.00]
|
||||
16:53:40.439835 db@open opening
|
||||
16:53:40.439835 journal@recovery F·1
|
||||
16:53:40.442835 journal@recovery recovering @12
|
||||
16:53:40.447835 memdb@flush created L0@15 N·18 S·69KiB "blo..-&\x8f,d69":"blo..n\x01\x04,v85"
|
||||
16:53:40.447835 version@stat F·[1 1] S·136KiB[69KiB 66KiB] Sc·[0.25 0.00]
|
||||
16:53:40.459551 db@janitor F·4 G·0
|
||||
16:53:40.459551 db@open done T·19.7158ms
|
||||
16:53:41.451901 db@close closing
|
||||
16:53:41.452419 db@close done T·517.1µs
|
||||
=============== Apr 24, 2024 (CST) ===============
|
||||
16:54:13.763685 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
|
||||
16:54:13.764685 version@stat F·[1 1] S·136KiB[69KiB 66KiB] Sc·[0.25 0.00]
|
||||
16:54:13.764685 db@open opening
|
||||
16:54:13.764685 journal@recovery F·1
|
||||
16:54:13.764685 journal@recovery recovering @16
|
||||
16:54:13.768693 memdb@flush created L0@18 N·18 S·64KiB "blo..\x17>\x16,v103":"blo..n\x01\x04,d97"
|
||||
16:54:13.769685 version@stat F·[2 1] S·200KiB[133KiB 66KiB] Sc·[0.50 0.00]
|
||||
16:54:13.780687 db@janitor F·5 G·0
|
||||
16:54:13.780687 db@open done T·16.0024ms
|
||||
16:54:13.872235 db@close closing
|
||||
16:54:13.872747 db@close done T·512µs
|
||||
=============== Apr 24, 2024 (CST) ===============
|
||||
17:02:38.948709 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
|
||||
17:02:38.948709 version@stat F·[2 1] S·200KiB[133KiB 66KiB] Sc·[0.50 0.00]
|
||||
17:02:38.948709 db@open opening
|
||||
17:02:38.948709 journal@recovery F·1
|
||||
17:02:38.949706 journal@recovery recovering @19
|
||||
17:02:38.953708 memdb@flush created L0@21 N·16 S·68KiB "blo..\x17>\x16,d107":"blo..n\x01\x03,d114"
|
||||
17:02:38.954701 version@stat F·[3 1] S·269KiB[202KiB 66KiB] Sc·[0.75 0.00]
|
||||
17:02:38.966383 db@janitor F·6 G·0
|
||||
17:02:38.966383 db@open done T·17.6743ms
|
||||
17:02:39.839266 db@close closing
|
||||
17:02:39.840346 db@close done T·1.0809ms
|
||||
=============== Apr 24, 2024 (CST) ===============
|
||||
17:03:47.548607 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
|
||||
17:03:47.549611 version@stat F·[3 1] S·269KiB[202KiB 66KiB] Sc·[0.75 0.00]
|
||||
17:03:47.549611 db@open opening
|
||||
17:03:47.549611 journal@recovery F·1
|
||||
17:03:47.550605 journal@recovery recovering @22
|
||||
17:03:47.554605 memdb@flush created L0@24 N·16 S·68KiB "blo..\n\x1f\",v137":"blo..n\x01\x03,d131"
|
||||
17:03:47.555606 version@stat F·[4 1] S·338KiB[271KiB 66KiB] Sc·[1.00 0.00]
|
||||
17:03:47.568002 db@janitor F·7 G·0
|
||||
17:03:47.568002 db@open done T·18.3915ms
|
||||
17:03:47.568507 table@compaction L0·4 -> L1·1 S·338KiB Q·140
|
||||
17:03:47.575714 table@build created L1@27 N·8 S·68KiB "blo..\n\x1f\",v137":"blo..n\x01\x03,v138"
|
||||
17:03:47.575714 version@stat F·[0 1] S·68KiB[0B 68KiB] Sc·[0.00 0.00]
|
||||
17:03:47.581257 table@compaction committed F-4 S-269KiB Ke·0 D·68 T·12.6705ms
|
||||
17:03:47.581763 table@remove removed @24
|
||||
17:03:47.581763 table@remove removed @21
|
||||
17:03:47.581763 table@remove removed @18
|
||||
17:03:47.581763 table@remove removed @15
|
||||
17:03:47.581763 table@remove removed @14
|
||||
17:03:47.659984 db@close closing
|
||||
17:03:47.659984 db@close done T·0s
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -98,5 +98,5 @@ func (os *OrderServer) Start() error {
|
|||
pb.RegisterChaincodeSupportServer(server.Server, os)
|
||||
|
||||
return server.Start()
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -104,3 +104,41 @@ func CheckAuth(ctx context.Context) (username string) {
|
|||
// 返回从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
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ type RequestServer struct {
|
|||
pb.UnimplementedPingServer
|
||||
}
|
||||
|
||||
var key string = "0123456789abcdef"
|
||||
|
||||
func (s *RequestServer) Login(ctx context.Context, in *pb.LoginRequest) (*pb.LoginReply, error) {
|
||||
//实现aes解密
|
||||
// 解密字符串
|
||||
|
@ -50,12 +52,6 @@ func (s *RequestServer) SayHello(ctx context.Context, in *pb.PingMessage) (*pb.P
|
|||
return &pb.PingMessage{Greeting: msg}, nil
|
||||
}
|
||||
|
||||
// 使用AES进行加解密
|
||||
// 定义要加密的字符串和密钥
|
||||
var (
|
||||
key string = "0123456789abcdef"
|
||||
)
|
||||
|
||||
func encrypt(plainText string, key string) (string, error) {
|
||||
keyBytes := []byte(key)
|
||||
|
||||
|
|
|
@ -50,6 +50,19 @@ func NewServer(address string) (*Server, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
//普通方法:一元拦截器(grpc.UnaryInterceptor)
|
||||
/*interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
||||
|
||||
if !is_ahtu {
|
||||
handler(ctx, req)
|
||||
is_ahtu = true
|
||||
}
|
||||
if Check(ctx) {
|
||||
handler(ctx, req)
|
||||
}
|
||||
return
|
||||
}
|
||||
*/
|
||||
var serverOpts []grpc.ServerOption
|
||||
|
||||
serverKeepAliveParameters := keepalive.ServerParameters{
|
||||
|
@ -69,6 +82,7 @@ func NewServer(address string) (*Server, error) {
|
|||
|
||||
serverOpts = append(serverOpts, grpc.ConnectionTimeout(connectionTimeout))
|
||||
|
||||
//serverOpts = append(serverOpts, grpc.UnaryInterceptor(interceptor))
|
||||
// create a gRPC server object
|
||||
grpcServer := grpc.NewServer(serverOpts...)
|
||||
request_server := &RequestServer{}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"fmt"
|
||||
"schain/config"
|
||||
"schain/peer/ledger"
|
||||
"schain/peer/shim/internal"
|
||||
"schain/peer/token"
|
||||
pb "schain/proto"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
@ -99,7 +99,7 @@ func (cs *ChaincodeServer) GetBlockInfo(ctx context.Context, e *pb.Empty) (*pb.B
|
|||
log.Debug("get BlockchainInfo fail", err)
|
||||
}
|
||||
for BlockNum != info.Height {
|
||||
info, err = Blockchain.GetBlockchainInfo()
|
||||
info, _ = Blockchain.GetBlockchainInfo()
|
||||
}
|
||||
atomic.AddUint64(&BlockNum, 1)
|
||||
return info, nil
|
||||
|
@ -133,12 +133,17 @@ func (cs *ChaincodeServer) Start() error {
|
|||
|
||||
var err error
|
||||
|
||||
tlsCfg, err := internal.LoadTLSConfig()
|
||||
/*tlsCfg, err := internal.LoadTLSConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
server, err := internal.NewServer(cs.Address, tlsCfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}*/
|
||||
|
||||
server, err := token.NewServer(cs.Address)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"schain/config"
|
||||
"schain/peer/shim/internal"
|
||||
"schain/peer/token"
|
||||
pb "schain/proto"
|
||||
"time"
|
||||
|
||||
|
@ -18,17 +18,18 @@ func userChaincodeStreamGetter(address string) (pb.ChaincodeSupportClient, error
|
|||
return nil, errors.New("flag 'peer.address' must be set")
|
||||
}
|
||||
|
||||
conf, err := internal.LoadConfig()
|
||||
/*conf, err := internal.LoadConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}*/
|
||||
|
||||
//此处address为peer address
|
||||
conn, err := token.NewClient(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conn, err := internal.NewClientConn(address, conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return internal.NewRegisterClient(conn)
|
||||
return token.NewRegisterClient(conn)
|
||||
}
|
||||
|
||||
type peerStreamGetter func(address string) (pb.ChaincodeSupportClient, error)
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
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
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package token
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
pb "schain/proto"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
)
|
||||
|
||||
const (
|
||||
dialTimeout = 10 * time.Second
|
||||
maxRecvMessageSize = 100 * 1024 * 1024 // 100 MiB
|
||||
maxSendMessageSize = 100 * 1024 * 1024 // 100 MiB
|
||||
|
||||
)
|
||||
|
||||
// 建立与grpc服务器的连接
|
||||
func NewClient(address string) (*grpc.ClientConn, error) {
|
||||
var conn *grpc.ClientConn
|
||||
//Keepalive 时间、超时时间和允许无流的连接
|
||||
kaOpts := keepalive.ClientParameters{
|
||||
Time: 1 * time.Minute,
|
||||
Timeout: 20 * time.Second,
|
||||
PermitWithoutStream: true,
|
||||
}
|
||||
|
||||
//gRPC 连接选项
|
||||
dialOpts := []grpc.DialOption{
|
||||
grpc.WithKeepaliveParams(kaOpts),
|
||||
grpc.WithBlock(),
|
||||
grpc.FailOnNonTempDialError(true),
|
||||
grpc.WithDefaultCallOptions(
|
||||
grpc.MaxCallRecvMsgSize(maxRecvMessageSize),
|
||||
grpc.MaxCallSendMsgSize(maxSendMessageSize),
|
||||
),
|
||||
}
|
||||
//取消证书认证
|
||||
dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
|
||||
//ctx, cancel := context.WithTimeout(context.Background(), dialTimeout)
|
||||
//defer cancel()
|
||||
conn, err := grpc.Dial(address, dialOpts...)
|
||||
//conn, err := grpc.DialContext(ctx, address, dialOpts...)
|
||||
if err != nil {
|
||||
log.Fatalf("did not connect: %s", err)
|
||||
}
|
||||
|
||||
//调用服务器上的 Login RPC 方法
|
||||
client := pb.NewPingClient(conn)
|
||||
|
||||
//对username和password进行aes加密
|
||||
usr, err := encrypt("Wuxinyu", key)
|
||||
if err != nil {
|
||||
panic("encrypt error")
|
||||
}
|
||||
pwd, err := encrypt("123456", key)
|
||||
if err != nil {
|
||||
panic("encrypt error")
|
||||
}
|
||||
loginReply, err := client.Login(context.Background(), &pb.LoginRequest{Username: usr, Password: pwd})
|
||||
if err != nil {
|
||||
log.Fatalf("Error when calling SayHello: %s", err)
|
||||
panic("wrong")
|
||||
}
|
||||
fmt.Println("Login Reply:", loginReply)
|
||||
conn.Close()
|
||||
|
||||
//Call SayHello,第二次连接
|
||||
requestToken := new(AuthToken)
|
||||
requestToken.Token = loginReply.Token
|
||||
|
||||
//创建一个超时的上下文连接
|
||||
ctx, cancel := context.WithTimeout(context.Background(), dialTimeout)
|
||||
defer cancel()
|
||||
dialOpts = append(dialOpts, grpc.WithPerRPCCredentials(requestToken))
|
||||
conn, err = grpc.DialContext(ctx, address, dialOpts...)
|
||||
if err != nil {
|
||||
log.Fatalf("did not connect: %s", err)
|
||||
}
|
||||
|
||||
client = pb.NewPingClient(conn)
|
||||
|
||||
helloreply, err := client.SayHello(context.Background(), &pb.PingMessage{Greeting: "foo"})
|
||||
if err != nil {
|
||||
log.Fatalf("Error when calling SayHello: %s", err)
|
||||
panic("connect error")
|
||||
}
|
||||
log.Printf("Response from server: %s", helloreply.Greeting)
|
||||
|
||||
//通过验证,返回客户端连接
|
||||
return conn, err
|
||||
}
|
||||
|
||||
func NewRegisterClient(conn *grpc.ClientConn) (pb.ChaincodeSupportClient, error) {
|
||||
return pb.NewChaincodeSupportClient(conn), nil
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package token
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
pb "schain/proto"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// 用于注册grpc服务
|
||||
type RequestServer struct {
|
||||
pb.UnimplementedPingServer
|
||||
}
|
||||
|
||||
var key string = "0123456789abcdef"
|
||||
|
||||
func (s *RequestServer) Login(ctx context.Context, in *pb.LoginRequest) (*pb.LoginReply, error) {
|
||||
//实现aes解密
|
||||
// 解密字符串
|
||||
de_name, err := decrypt(in.Username, key)
|
||||
if err != nil {
|
||||
panic("Decryption error")
|
||||
}
|
||||
de_password, err := decrypt(in.Password, key)
|
||||
if err != nil {
|
||||
panic("Decryption error")
|
||||
}
|
||||
fmt.Println("Loginrequest: ", de_name)
|
||||
if de_name == "Wuxinyu" && de_password == "123456" {
|
||||
tokenString := CreateToken(in.Username)
|
||||
return &pb.LoginReply{Status: "200", Token: tokenString}, nil
|
||||
|
||||
} else {
|
||||
return &pb.LoginReply{Status: "403", Token: ""}, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// SayHello 生成对 Ping 请求的响应
|
||||
func (s *RequestServer) SayHello(ctx context.Context, in *pb.PingMessage) (*pb.PingMessage, error) {
|
||||
//生成响应消息
|
||||
msg := "bar"
|
||||
// 从上下文中检查用户认证信息
|
||||
userName := CheckAuth(ctx)
|
||||
//将用户名添加到消息中
|
||||
msg += " " + userName
|
||||
return &pb.PingMessage{Greeting: msg}, nil
|
||||
}
|
||||
|
||||
func encrypt(plainText string, key string) (string, error) {
|
||||
keyBytes := []byte(key)
|
||||
|
||||
block, err := aes.NewCipher(keyBytes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 创建一个加密器
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 创建一个随机的 nonce,长度必须与加密块大小相同
|
||||
nonce := make([]byte, gcm.NonceSize())
|
||||
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 使用 nonce 加密数据
|
||||
ciphertext := gcm.Seal(nonce, nonce, []byte(plainText), nil)
|
||||
return base64.StdEncoding.EncodeToString(ciphertext), nil
|
||||
}
|
||||
|
||||
func decrypt(ciphertext string, key string) (string, error) {
|
||||
decodedCiphertext, err := base64.StdEncoding.DecodeString(ciphertext)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher([]byte(key))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 创建一个解密器
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 从密文中提取 nonce
|
||||
nonceSize := gcm.NonceSize()
|
||||
if len(decodedCiphertext) < nonceSize {
|
||||
return "", fmt.Errorf("ciphertext too short")
|
||||
}
|
||||
nonce := decodedCiphertext[:nonceSize]
|
||||
ciphertextBytes := decodedCiphertext[nonceSize:]
|
||||
|
||||
// 解密数据
|
||||
plaintext, err := gcm.Open(nil, nonce, ciphertextBytes, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(plaintext), nil
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package token
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
pb "schain/proto"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
)
|
||||
|
||||
const (
|
||||
//服务器在处理任务或执行操作时,至少需要等待1分钟的时间间隔
|
||||
serverMinInterval = time.Duration(1) * time.Minute
|
||||
//5秒连接超时
|
||||
connectionTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
Listener net.Listener
|
||||
Server *grpc.Server
|
||||
}
|
||||
|
||||
func (s *Server) Start() error {
|
||||
if s.Listener == nil {
|
||||
return errors.New("nil listener")
|
||||
}
|
||||
|
||||
if s.Server == nil {
|
||||
return errors.New("nil server")
|
||||
}
|
||||
|
||||
return s.Server.Serve(s.Listener)
|
||||
}
|
||||
|
||||
func (s *Server) Stop() {
|
||||
if s.Server != nil {
|
||||
s.Server.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
func NewServer(address string) (*Server, error) {
|
||||
if address == "" {
|
||||
return nil, errors.New("server listen address not provided")
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//普通方法:一元拦截器(grpc.UnaryInterceptor)
|
||||
/*interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
||||
|
||||
if !is_ahtu {
|
||||
handler(ctx, req)
|
||||
is_ahtu = true
|
||||
}
|
||||
if Check(ctx) {
|
||||
handler(ctx, req)
|
||||
}
|
||||
return
|
||||
}
|
||||
*/
|
||||
var serverOpts []grpc.ServerOption
|
||||
|
||||
serverKeepAliveParameters := keepalive.ServerParameters{
|
||||
Time: 1 * time.Minute,
|
||||
Timeout: 20 * time.Second,
|
||||
}
|
||||
serverOpts = append(serverOpts, grpc.KeepaliveParams(serverKeepAliveParameters))
|
||||
serverOpts = append(serverOpts, grpc.MaxSendMsgSize(maxSendMessageSize))
|
||||
serverOpts = append(serverOpts, grpc.MaxRecvMsgSize(maxRecvMessageSize))
|
||||
|
||||
kep := keepalive.EnforcementPolicy{
|
||||
MinTime: serverMinInterval,
|
||||
PermitWithoutStream: true,
|
||||
}
|
||||
|
||||
serverOpts = append(serverOpts, grpc.KeepaliveEnforcementPolicy(kep))
|
||||
|
||||
serverOpts = append(serverOpts, grpc.ConnectionTimeout(connectionTimeout))
|
||||
|
||||
//serverOpts = append(serverOpts, grpc.UnaryInterceptor(interceptor))
|
||||
// create a gRPC server object
|
||||
grpcServer := grpc.NewServer(serverOpts...)
|
||||
request_server := &RequestServer{}
|
||||
pb.RegisterPingServer(grpcServer, request_server)
|
||||
|
||||
return &Server{Listener: listener, Server: grpcServer}, err
|
||||
|
||||
}
|
Loading…
Reference in New Issue