grpc 攔截器【 go 和 asp.net core的實現】

在 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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章