在 asp.ner core 5.0 Grpc HttpApi 和jwt的集成 和跨域【https雙向認證】和 Go Grpc Jwt身份認證和Gateway集成以及HTTPS雙向認證 我們 獲取用戶名都是通過方法的,在這裏我們來用攔截器實現一下。
GO
大類可分爲兩種 RPC 方法,與攔截器的對應關係是:普通方法:一元攔截器(grpc.UnaryInterceptor);流方法:流攔截器(grpc.StreamInterceptor)。
1.攔截器的實現 我們來看看他的實現。在\gogrpcjwt\api\authtoken.go文件我們增加方法 AuthInterceptor【我們的值 是通過context來存儲的】
/* ctx context.Context:請求上下文 req interface{}:RPC 方法的請求參數 info *UnaryServerInfo:RPC 方法的所有信息 handler UnaryHandler:RPC 方法本身 */ func AuthInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { userName := CheckAuth(ctx) log.Printf("gRPC method: %s, %v", info.FullMethod, req) newCtx := ctx if len(userName) > 0 { //使用context.WithValue添加了值後,可以用Value(key)方法獲取值 newCtx = context.WithValue(ctx, "username", userName) //log.Println(newCtx.Value("username")) } return handler(newCtx, req) }
2.註冊攔截器 servertls\main.go
//rpcServer := grpc.NewServer() opts := []grpc.ServerOption{ grpc_middleware.WithUnaryServerChain( api.AuthInterceptor, )} rpcServer := grpc.NewServer(opts...)
3.獲取用戶信息 修改api/handler.go的SayHello 方法:
//userName := CheckAuth(ctx) userName := fmt.Sprintf("%v", ctx.Value("username"))
4運行結果正常
D:\GoProject\src\gogrpcjwt\clienttls>go run main.go 2021/01/06 16:45:24 Response from server: bar gavin http call..... 2021/01/06 16:45:24 {"greeting":"bar gavin"}
asp.net core 5.0
在C# 裏面分客戶端【個人覺得 意義不大,比如我用html 只能訪問httpapi】 和服務端
1.創建攔截器AuthInterceptor.cs ,繼承攔截器基類 Interceptor
using Grpc.Core; using Grpc.Core.Interceptors; using Microsoft.IdentityModel.Tokens; using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; using System.Text; using System.Threading.Tasks; namespace grpcserver { public class AuthInterceptor:Interceptor { const string tokenSchema = "Bearer"; const string tokenIssuer = "https://localhost:5001"; const string tokenAudience = "grpc"; const string tokenSecurityKey = "asp.netcore5.0grpcjwt"; public override Task<TResponse> UnaryServerHandler<TRequest, TResponse>( TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation) { var userContext = context.GetHttpContext().User; string userName = userContext.FindFirstValue(ClaimTypes.Name); if (string.IsNullOrEmpty(userName)) { string tokenStr = context.GetHttpContext().Request?.Headers["Authorization"]; if (!string.IsNullOrEmpty(tokenStr)) { if (tokenStr.StartsWith(tokenSchema)) { tokenStr = tokenStr.Split(' ')[1]; } SecurityToken token; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenSecurityKey)); ClaimsPrincipal claims = new JwtSecurityTokenHandler().ValidateToken(tokenStr, new TokenValidationParameters { ValidAudience = tokenAudience, ValidIssuer = tokenIssuer, IssuerSigningKey = key }, out token); context.GetHttpContext().User = claims; } } return continuation(request, context); } } }
2.註冊攔截器 Startup.cs的ConfigureServices 方法
services.AddGrpc(x=>x.Interceptors.Add<AuthInterceptor>());
3.修改調用程序GreeterService.cs的SayHello
// var userName= CheckAuth(context)??string.Empty; var userName = context.GetHttpContext().User.FindFirstValue(ClaimTypes.Name);
4.運行結果:
備註,像這種獲取信息的, 我個人還是推薦 直接用方法 調用來的實惠,攔截器 類似管道 我一般 用於處理系統級的問題, 開發感覺不到, 比如 統一日誌 下載地址: https://github.com/dz45693/asp.netgrpccert.git 【C#】 https://github.com/dz45693/gogrpcjwt.git 【Go】 參考 https://www.cnblogs.com/stulzq/p/11840535.html