grpc拦截器+metadata进行接口统一校验

grpc拦截器+metadata进行接口统一校验

    • hello.proto
    • proto生成go文件命令
    • client.go
      • 方法一:自定义拦截器,实现统一参数校验
      • 方法二:使用grpc内置拦截器,需要自定义结构体,实现credentials.PerRPCCredentials接口中的方法
    • server.go

hello.proto

syntax = "proto3";option go_package ="./;proto";service Server {rpc SayHello(HelloReq) returns (HelloRes);
}message HelloReq{string name = 1;
}message HelloRes{string msg = 1;
}

proto生成go文件命令

protoc --go_out=. --go-grpc_out=. hello.proto

client.go

方法一:自定义拦截器,实现统一参数校验

package mainimport ("Go_Bible/grpc_token_auth_test/proto""context""fmt""google.golang.org/grpc""google.golang.org/grpc/metadata"
)func main() {/*自定义拦截器,搭配metadata元数据,进行登录验证*/authInterceptor := func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {//fmt.Println("客户端封装metadata,封装auth")// 手动创建元数据md := metadata.New(map[string]string{"appid":      "10010","access_key": "1234",})// 创建出站请求的上下文ctx = metadata.NewOutgoingContext(ctx, md)err := invoker(ctx, method, req, reply, cc, opts...)if err != nil {fmt.Println("客户端接口调用错误-->" + err.Error())}return err}// 放入拦截器opt := grpc.WithUnaryInterceptor(authInterceptor)var opts []grpc.DialOptionopts = append(opts, opt)opts = append(opts, grpc.WithInsecure())conn, err := grpc.Dial("localhost:15001", opts...)if err != nil {panic("客户端拨号失败-->" + err.Error())}client := proto.NewServerClient(conn)res, err := client.SayHello(context.Background(), &proto.HelloReq{Name: "kevin",})if err != nil {panic("客户端调用SayHello接口失败-->" + err.Error() + "\n")}fmt.Println("客户端调用接口成功:" + res.Msg)
}

方法二:使用grpc内置拦截器,需要自定义结构体,实现credentials.PerRPCCredentials接口中的方法

package mainimport ("Go_Bible/grpc_token_auth_test/proto""context""fmt""google.golang.org/grpc"
)type customCredential struct{}// 获取元数据接口,自定义验证相关的元数据
func (c customCredential) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error){return map[string]string{"appid" : "10010","access_key" : "1234",}, nil
}// 是否安全传输
func (c customCredential) RequireTransportSecurity() bool{return false
}func main() {///*自定义拦截器,搭配metadata元数据,进行登录验证*///authInterceptor := func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {//	//fmt.Println("客户端封装metadata,封装auth")//	// 手动创建元数据//	md := metadata.New(map[string]string{//		"appid":      "10010",//		"access_key": "1234",//	})//	// 创建出站请求的上下文//	ctx = metadata.NewOutgoingContext(ctx, md)//	err := invoker(ctx, method, req, reply, cc, opts...)//	if err != nil {//		fmt.Println("客户端接口调用错误-->" + err.Error())//	}//	return err//}// 放入拦截器//opt := grpc.WithUnaryInterceptor(authInterceptor)// 创建验证相关的拦截器opt := grpc.WithPerRPCCredentials(customCredential{})var opts []grpc.DialOptionopts = append(opts, opt)opts = append(opts, grpc.WithInsecure())conn, err := grpc.Dial("localhost:15001", opts...)if err != nil {panic("客户端拨号失败-->" + err.Error())}client := proto.NewServerClient(conn)res, err := client.SayHello(context.Background(), &proto.HelloReq{Name: "kevin",})if err != nil {panic("客户端调用SayHello接口失败-->" + err.Error() + "\n")}fmt.Println("客户端调用接口成功:" + res.Msg)
}

server.go

package mainimport ("Go_Bible/grpc_token_auth_test/proto""context""fmt""google.golang.org/grpc""google.golang.org/grpc/codes""google.golang.org/grpc/metadata""google.golang.org/grpc/status""net"
)type Server struct {proto.UnimplementedServerServer
}func (s *Server) SayHello(ctx context.Context, req *proto.HelloReq) (*proto.HelloRes, error) {return &proto.HelloRes{Msg: "Hello : " + req.Name,}, nil
}func main() {// 创建验证拦截器interceptor := func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {fmt.Println("服务端开始对接口拦截")/*开始解析元数据,进行接口验证*/md, ok := metadata.FromIncomingContext(ctx)if !ok {fmt.Println("服务端获取元数据失败")return resp, status.Error(codes.Unauthenticated, "服务端获取metadata失败")}var (appid      stringaccess_key string)if val, ok := md["appid"]; ok {appid = val[0]}if val, ok := md["access_key"]; ok {access_key = val[0]}// 对appid跟access_token进行验证if appid != "10010" || access_key != "1234" {return resp, status.Error(codes.Unauthenticated, "服务端接口校验失败")}fmt.Println("服务端接口统一校验通过")// 校验通过,继续调用接口resp, err = handler(ctx, req)fmt.Println("服务端接口拦截结束")return resp, err}// 注册拦截器opt := grpc.UnaryInterceptor(interceptor)var opts []grpc.ServerOptionopts = append(opts, opt)// 创建服务server := grpc.NewServer(opts...)// 注册服务proto.RegisterServerServer(server, &Server{})lis, err := net.Listen("tcp", "0.0.0.0:15001")if err != nil {panic("服务端监听失败-->" + err.Error())}err = server.Serve(lis)if err != nil {panic("服务端开启服务失败-->" + err.Error())}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/6539.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rust 实现GUI页面方法

rust 实现GUI页面方法 position-based 特点 精确控制:开发者可以精确控制每个元素的位置和大小,这在某些需要精细布局调整的应用场景中非常有用。直观:对于简单的界面,使用基于位置的布局方式很直观,容易理解。灵活…

python爬虫实战

import requests import json yesinput(输入页数:) yesint(yes)headers {"accept": "application/json, text/plain, */*","accept-language": "zh-CN,zh;q0.9","content-type": "application/json",…

一对一WebRTC视频通话系列(三)——leave和peer-leave信令实现

本篇博客主要分为两部分,第一部分为leave信令的实现,即当有客户端离开房间后,服务端和其他在房间内的客户需知晓。第二部分为媒体协商和网络协商相关API。 本系列博客主要记录一对一WebRTC视频通话实现过程中的一些重点,代码全部进…

渗透之sql盲注(时间/boolean盲注)

sql盲注:sql盲注意思是我们并不能在web页面中看到具体的信息,我们只能通过输入的语句的真假来判断。从而拿到我们想要的信息。 我们通常使用ascii值来进行盲注。 目录 手动注入: 时间盲注: 布尔盲注: python脚本注…

【Java】基本程序设计结构(一)

前言:现在,假定已经成功安装了JDK,并且能够运行上篇示例程序。本篇将开始介绍Java程序中的基本设计结构,其中包括:一个简单的Java应用,注释,数据类型,变量与常量,运算符&…

【深度学习基础(3)】初识神经网络之深度学习hello world

文章目录 一. 训练Keras中的MNIST数据集二. 工作流程1. 构建神经网络2. 准备图像数据3. 训练模型4. 利用模型进行预测5. (新数据上)评估模型精度 本节将首先给出一个神经网络示例,引出如下概念。了解完本节后,可以对神经网络在代码上的实现有一个整体的了…

【架构系列】RabbitMQ应用场景及在实际项目中如何搭建可靠的RabbitMQ架构体系

作者:后端小肥肠 创作不易,未经允许禁止转载。 1. 前言 RabbitMQ,作为一款高性能、可靠的消息队列软件,已经成为许多企业和开发团队的首选之一。它的灵活性和可扩展性使得它适用于各种应用场景,从简单的任务队列到复杂的分布式系统…

算法设计与分析——期末1h

目录 第一章 算法的定义 算法的三要素 算法的基本性质 算法的时间复杂度数量级: 第二章 兔子繁殖问题(递推法) 猴子吃桃问题(递推法) 穿越沙漠问题(递推法(倒推)) 百钱百…

解决Maven本地仓库存在依赖包还需要远程下载的问题

背景 公司有自己maven私服,正在在私服可以使用的情况,打包是没问题的。但是这次是由于公司大楼整体因电路检修而停电,所有服务器关机,包括maven私服服务器。然后当天确有一个包需要打,这个时候发现死活打不了&#xf…

力扣数据库题库学习(5.4日)--1661. 每台机器的进程平均运行时间

1661. 每台机器的进程平均运行时间 问题链接 解题思路 现在有一个工厂网站由几台机器运行,每台机器上运行着 相同数量的进程 。编写解决方案,计算每台机器各自完成一个进程任务的平均耗时。 完成一个进程任务的时间指进程的’end’ 时间戳 减去 ‘sta…

线性数据结构-手写链表-LinkList

为什么需要手写实现数据结构? 其实技术的本身就是基础的积累和搭建的过程,基础扎实 地基平稳 万丈高楼才会久战不衰,做技术能一通百,百通千就不怕有再难得技术了。 一:链表的分类 主要有单向,双向和循环链表…

飞书API(7):MySQL 入库通用版本

一、引入 在上一篇介绍了如何使用 pandas 处理飞书接口返回的数据,并将处理好的数据入库。最终的代码拓展性太差,本篇来探讨下如何使得上一篇的最终代码拓展性更好!为什么上一篇的代码拓展性太差呢?我总结了几点: 列…

福布斯AI 50榜单发布!新兴势力颠覆传统,叫板谷歌、微软

整理 | 王轶群 责编 | 唐小引 出品丨AI 科技大本营(ID:rgznai100) ChatGPT带来的生成式人工智能热浪,促使众多企业争先恐后地试图实现生成式人工智能的最新进展。一个新的帮助企业开发和部署人工智能驱动的应用程序的科技经济体系…

Spring Boot面试知识点总结(经典15问)

Spring Boot面试知识点总结(问答合集) 文章目录 Spring Boot面试知识点总结(问答合集)一、Spring Boot简介二、核心特性三、面试问题及答案问题1:Spring Boot的核心配置文件是什么?问题2:Spring…

NFS共享存储服务

一、NFS概述 1、简介 NFS是一种基于TCP/IP传输的网络文件系统协议。 NFS 服务的实现依赖于 RPC(Remote Process Call,远端过程调用)机制,通过使用 NFS 协议,客户机可以像访问本地目录一样访问远程服务器中的共享资源…

BUUCTF——web题目练习

[极客大挑战 2019]LoveSQL 输入1 123 输入1 123 输入2 123 这里可以看出注入位置为password的后面,开始手动注入 闭合方式为1 [极客大挑战 2019]Secret File 查看页面源代码,发现里面有一个跳转页面的连接,点击进去,查看这个…

Llama改进之——SwiGLU激活函数

引言 今天介绍LLAMA模型引入的关于激活函数的改进——SwiGLU1,该激活函数取得了不错的效果,得到了广泛地应用。 SwiGLU是GLU的一种变体,其中包含了GLU和Swish激活函数。 GLU GLU(Gated Linear Units,门控线性单元)2引入了两个不同的线性层…

83、动态规划-打家劫舍

思路: 首先使用递归方式求出最优解。从每个房屋开始,分别考虑偷与不偷两种情况,然后递归地对后续的房屋做同样的决策。这种方法确保了可以找到在不触发警报的情况下可能的最高金额。 代码如下: public static int rob(int[] nu…

【C++】深入剖析C++中的lambda表达式包装器bind

目录 一、lambda表达式 1、引入 2、lambda表达式 3、lambda表达式语法 ​4、lambda 的底层逻辑 二、包装器 1、包装器的表达式 ​ 2、实例化多份 3、可调用对象类型 4、实操例题 三、bind 1、bind 的表达式 2、调整参数的位置 3、绑定参数 一、lambda表达式 1、引…

wpf线程中更新UI的4种方式

在wpf中,更新UI上面的数据,那是必经之路,搞不好,就是死锁,或者没反应,很多时候,都是嵌套的非常深导致的。但是更新UI的方式,有很多的种,不同的方式,表示的意思…