摘要:帶入對(duì)方法做自定義認(rèn)證原文地址帶入對(duì)方法做自定義認(rèn)證項(xiàng)目地址前言在前面的章節(jié)中,我們介紹了兩種證書(shū)算一種可全局認(rèn)證的方法證書(shū)認(rèn)證基于的證書(shū)認(rèn)證而在實(shí)際需求中,常常會(huì)對(duì)某些模塊的方法做特殊認(rèn)證或校驗(yàn)。
帶入gRPC:對(duì) RPC 方法做自定義認(rèn)證
原文地址:帶入gRPC:對(duì) RPC 方法做自定義認(rèn)證
項(xiàng)目地址:https://github.com/EDDYCJY/go...
在前面的章節(jié)中,我們介紹了兩種(證書(shū)算一種)可全局認(rèn)證的方法:
TLS 證書(shū)認(rèn)證
基于 CA 的 TLS 證書(shū)認(rèn)證
Unary and Stream interceptor
而在實(shí)際需求中,常常會(huì)對(duì)某些模塊的 RPC 方法做特殊認(rèn)證或校驗(yàn)。今天將會(huì)講解、實(shí)現(xiàn)這塊的功能點(diǎn)
課前知識(shí)type PerRPCCredentials interface { GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) RequireTransportSecurity() bool }
在 gRPC 中默認(rèn)定義了 PerRPCCredentials,它就是本章節(jié)的主角,是 gRPC 默認(rèn)提供用于自定義認(rèn)證的接口,它的作用是將所需的安全認(rèn)證信息添加到每個(gè) RPC 方法的上下文中。其包含 2 個(gè)方法:
GetRequestMetadata:獲取當(dāng)前請(qǐng)求認(rèn)證所需的元數(shù)據(jù)(metadata)
RequireTransportSecurity:是否需要基于 TLS 認(rèn)證進(jìn)行安全傳輸
目錄結(jié)構(gòu)新建 simple_token_server/server.go 和 simple_token_client/client.go,目錄結(jié)構(gòu)如下:
go-grpc-example ├── client │?? ├── simple_client │?? ├── simple_http_client │?? ├── simple_token_client │?? └── stream_client ├── conf ├── pkg ├── proto ├── server │?? ├── simple_http_server │?? ├── simple_server │?? ├── simple_token_server │?? └── stream_server └── vendorgRPC Client
package main import ( "context" "log" "google.golang.org/grpc" "github.com/EDDYCJY/go-grpc-example/pkg/gtls" pb "github.com/EDDYCJY/go-grpc-example/proto" ) const PORT = "9004" type Auth struct { AppKey string AppSecret string } func (a *Auth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { return map[string]string{"app_key": a.AppKey, "app_secret": a.AppSecret}, nil } func (a *Auth) RequireTransportSecurity() bool { return true } func main() { tlsClient := gtls.Client{ ServerName: "go-grpc-example", CertFile: "../../conf/server/server.pem", } c, err := tlsClient.GetTLSCredentials() if err != nil { log.Fatalf("tlsClient.GetTLSCredentials err: %v", err) } auth := Auth{ AppKey: "eddycjy", AppSecret: "20181005", } conn, err := grpc.Dial(":"+PORT, grpc.WithTransportCredentials(c), grpc.WithPerRPCCredentials(&auth)) ... }
在 Client 端,重點(diǎn)實(shí)現(xiàn) type PerRPCCredentials interface 所需的方法,關(guān)注兩點(diǎn)即可:
struct Auth:GetRequestMetadata、RequireTransportSecurity
grpc.WithPerRPCCredentials
Serverpackage main import ( "context" "log" "net" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" "github.com/EDDYCJY/go-grpc-example/pkg/gtls" pb "github.com/EDDYCJY/go-grpc-example/proto" ) type SearchService struct { auth *Auth } func (s *SearchService) Search(ctx context.Context, r *pb.SearchRequest) (*pb.SearchResponse, error) { if err := s.auth.Check(ctx); err != nil { return nil, err } return &pb.SearchResponse{Response: r.GetRequest() + " Token Server"}, nil } const PORT = "9004" func main() { ... } type Auth struct { appKey string appSecret string } func (a *Auth) Check(ctx context.Context) error { md, ok := metadata.FromIncomingContext(ctx) if !ok { return status.Errorf(codes.Unauthenticated, "自定義認(rèn)證 Token 失敗") } var ( appKey string appSecret string ) if value, ok := md["app_key"]; ok { appKey = value[0] } if value, ok := md["app_secret"]; ok { appSecret = value[0] } if appKey != a.GetAppKey() || appSecret != a.GetAppSecret() { return status.Errorf(codes.Unauthenticated, "自定義認(rèn)證 Token 無(wú)效") } return nil } func (a *Auth) GetAppKey() string { return "eddycjy" } func (a *Auth) GetAppSecret() string { return "20181005" }
在 Server 端就更簡(jiǎn)單了,實(shí)際就是調(diào)用 metadata.FromIncomingContext 從上下文中獲取 metadata,再在不同的 RPC 方法中進(jìn)行認(rèn)證檢查
驗(yàn)證重新啟動(dòng) server.go 和 client.go,得到以下結(jié)果:
$ go run client.go 2018/10/05 20:59:58 resp: gRPC Token Server
修改 client.go 的值,制造兩者不一致,得到無(wú)效結(jié)果:
$ go run client.go 2018/10/05 21:00:05 client.Search err: rpc error: code = Unauthenticated desc = invalid token exit status 1一個(gè)個(gè)加太麻煩
我相信你肯定會(huì)問(wèn)一個(gè)個(gè)加,也太麻煩了吧?有這個(gè)想法的你,應(yīng)當(dāng)把 type PerRPCCredentials interface 做成一個(gè)攔截器(interceptor)
總結(jié)本章節(jié)比較簡(jiǎn)單,主要是針對(duì) RPC 方法的自定義認(rèn)證進(jìn)行了介紹,如果是想做全局的,建議是舉一反三從攔截器下手哦
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/29522.html
摘要:帶入及相關(guān)介紹原文地址帶入及相關(guān)介紹項(xiàng)目地址作為開(kāi)篇章,將會(huì)介紹相關(guān)的一些知識(shí)。 帶入gRPC:gRPC及相關(guān)介紹 原文地址:帶入gRPC:gRPC及相關(guān)介紹 項(xiàng)目地址:go-grpc-example 作為開(kāi)篇章,將會(huì)介紹 gRPC 相關(guān)的一些知識(shí)。簡(jiǎn)單來(lái)講 gRPC 是一個(gè) 基于 HTTP/2 協(xié)議設(shè)計(jì)的 RPC 框架,它采用了 Protobuf 作為 IDL 你是否有過(guò)疑惑,它們都...
摘要:原文地址帶入及相關(guān)介紹項(xiàng)目地址作為開(kāi)篇章,將會(huì)介紹相關(guān)的一些知識(shí)。 原文地址:帶入gRPC:gRPC及相關(guān)介紹 項(xiàng)目地址:go-grpc-example 作為開(kāi)篇章,將會(huì)介紹 gRPC 相關(guān)的一些知識(shí)。簡(jiǎn)單來(lái)講 gRPC 是一個(gè) 基于 HTTP/2 協(xié)議設(shè)計(jì)的 RPC 框架,它采用了 Protobuf 作為 IDL 你是否有過(guò)疑惑,它們都是些什么?本文將會(huì)介紹一些常用的知識(shí)和概念,更詳...
摘要:帶入原文地址帶入項(xiàng)目地址前言本章節(jié)將介紹的流式,分為三種類(lèi)型服務(wù)器端流式客戶(hù)端流式雙向流式流任何技術(shù),因?yàn)橛型袋c(diǎn),所以才有了存在的必要性。這一次性涉及的數(shù)據(jù)量確實(shí)大在同步完成后,也有人馬上會(huì)去查閱數(shù)據(jù),為了新的一天籌備。 帶入gRPC:gRPC Streaming, Client and Server 原文地址:帶入gRPC:gRPC Streaming, Client and Ser...
摘要:帶入基于的證書(shū)認(rèn)證原文地址帶入基于的證書(shū)認(rèn)證項(xiàng)目地址前言在上一章節(jié)中,我們提出了一個(gè)問(wèn)題。其遵守標(biāo)準(zhǔn)根證書(shū)根證書(shū)是屬于根證書(shū)頒發(fā)機(jī)構(gòu)的公鑰證書(shū)。目標(biāo)是基于進(jìn)行認(rèn)證 帶入gRPC:基于 CA 的 TLS 證書(shū)認(rèn)證 原文地址:帶入gRPC:基于 CA 的 TLS 證書(shū)認(rèn)證項(xiàng)目地址:https://github.com/EDDYCJY/go... 前言 在上一章節(jié)中,我們提出了一個(gè)問(wèn)題。就是...
摘要:帶入分布式鏈路追蹤原文地址帶入分布式鏈路追蹤項(xiàng)目地址前言在實(shí)際應(yīng)用中,你做了那么多端,寫(xiě)了個(gè)方法。想看看方法的指標(biāo),卻無(wú)處下手本文將通過(guò)搭建一個(gè)分布式鏈路追蹤系統(tǒng)來(lái)實(shí)現(xiàn)查看整個(gè)系統(tǒng)的鏈路性能等指標(biāo) 帶入gRPC:分布式鏈路追蹤 gRPC + Opentracing + Zipkin 原文地址:帶入gRPC:分布式鏈路追蹤 gRPC + Opentracing + Zipkin項(xiàng)目地址:...
閱讀 3094·2023-04-26 00:32
閱讀 570·2019-08-30 15:52
閱讀 2172·2019-08-30 15:52
閱讀 3449·2019-08-30 15:44
閱讀 3340·2019-08-30 14:09
閱讀 1477·2019-08-29 15:15
閱讀 3454·2019-08-28 18:12
閱讀 1165·2019-08-26 13:55