• 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.拦截器的实现   我们来看看他的实现。在gogrpcjwtapiauthtoken.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.注册拦截器 servertlsmain.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:GoProjectsrcgogrpcjwtclienttls>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
  • 相关阅读:
    课程作业03-1
    课程作业02
    课程作业01:模仿JavaAppArguments.java示例,编写一个程序,此程序从命令行接收多个数字,求和之后输出结果。
    《大道至简》第一章读后感,伪代码
    《美国教授写给被开除中国留学生的信》阅读笔记
    《大道至简》读后感
    《需求工程——软件建模与分析》阅读笔记02
    《需求工程——软件建模与分析》阅读笔记01
    微信小游戏开发笔记03
    微信小游戏开发笔记02
  • 原文地址:https://www.cnblogs.com/majiang/p/14242137.html
Copyright © 2020-2023  润新知