带入gRPC:对 RPC 方法做自定义认证
带入gRPC:对 RPC 方法做自定义认证
原文地址:带入gRPC:对 RPC 方法做自定义认证
项目地址:https://github.com/EDDYCJY/go...
前言
在前面的章节中,我们介绍了两种(证书算一种)可全局认证的方法:
而在实际需求中,常常会对某些模块的 RPC 方法做特殊认证或校验。今天将会讲解、实现这块的功能点
课前知识
type PerRPCCredentials interface {
GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
RequireTransportSecurity() bool
}
在 gRPC 中默认定义了 PerRPCCredentials,它就是本章节的主角,是 gRPC 默认提供用于自定义认证的接口,它的作用是将所需的安全认证信息添加到每个 RPC 方法的上下文中。其包含 2 个方法:
- GetRequestMetadata:获取当前请求认证所需的元数据(metadata)
- RequireTransportSecurity:是否需要基于 TLS 认证进行安全传输
目录结构
新建 simple_token_server/server.go 和 simple_token_client/client.go,目录结构如下:
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
└── vendor
gRPC
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 端,重点实现 type PerRPCCredentials interface 所需的方法,关注两点即可:
- struct Auth:GetRequestMetadata、RequireTransportSecurity
- grpc.WithPerRPCCredentials
Server
package 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, "自定义认证 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, "自定义认证 Token 无效")
}
return nil
}
func (a *Auth) GetAppKey() string {
return "eddycjy"
}
func (a *Auth) GetAppSecret() string {
return "20181005"
}
在 Server 端就更简单了,实际就是调用 metadata.FromIncomingContext 从上下文中获取 metadata,再在不同的 RPC 方法中进行认证检查
验证
重新启动 server.go 和 client.go,得到以下结果:
$ go run client.go
2018/10/05 20:59:58 resp: gRPC Token Server
修改 client.go 的值,制造两者不一致,得到无效结果:
$ go run client.go
2018/10/05 21:00:05 client.Search err: rpc error: code = Unauthenticated desc = invalid token
exit status 1
一个个加太麻烦
我相信你肯定会问一个个加,也太麻烦了吧?有这个想法的你,应当把 type PerRPCCredentials interface 做成一个拦截器(interceptor)
总结
本章节比较简单,主要是针对 RPC 方法的自定义认证进行了介绍,如果是想做全局的,建议是举一反三从拦截器下手哦
带入gRPC:对 RPC 方法做自定义认证的更多相关文章
- DRF认证、自定义认证和权限、自定义权限
源码分析 """ 1)APIView的dispath(self, request, *args, **kwargs) 2)dispath方法内 self.initial( ...
- drf三大认证:认证组件-权限组件-权限六表-自定义认证组件的使用
三大认证工作原理简介 认证.权限.频率 源码分析: from rest_framework.views import APIView 源码分析入口: 内部的三大认证方法封装: 三大组件的原理分析: 权 ...
- 跟我一起学Go系列:Go gRPC 安全认证方式-Token和自定义认证
Go gRPC 系列: 跟我一起学Go系列:gRPC安全认证机制-SSL/TLS认证 跟我一起学 Go 系列:gRPC 拦截器使用 跟我一起学 Go 系列:gRPC 入门必备 接上一篇继续讲 gRPC ...
- gRPC【RPC自定义http2.0协议传输】
gRPC 简介 gRPC是由Google公司开源的高性能RPC框架. gRPC支持多语言 gRPC原生使用C.Java.Go进行了三种实现,而C语言实现的版本进行封装后又支持C++.C#.Node.O ...
- asp.net core 自定义认证方式--请求头认证
asp.net core 自定义认证方式--请求头认证 Intro 最近开始真正的实践了一些网关的东西,最近写几篇文章分享一下我的实践以及遇到的问题. 本文主要介绍网关后面的服务如何进行认证. 解决思 ...
- go微服务框架go-micro深度学习(四) rpc方法调用过程详解
上一篇帖子go微服务框架go-micro深度学习(三) Registry服务的注册和发现详细解释了go-micro是如何做服务注册和发现在,服务端注册server信息,client获取server的地 ...
- go微服务框架go-micro深度学习 rpc方法调用过程详解
摘要: 上一篇帖子go微服务框架go-micro深度学习(三) Registry服务的注册和发现详细解释了go-micro是如何做服务注册和发现在,服务端注册server信息,client获取serv ...
- Spring集成shiro做登陆认证
一.背景 其实很早的时候,就在项目中有使用到shiro做登陆认证,直到今天才又想起来这茬,自己抽空搭了一个spring+springmvc+mybatis和shiro进行集成的种子项目,当然里面还有很 ...
- 【Spring Security】六、自定义认证处理的过滤器
这里接着上一章的自定义过滤器,这里主要的是配置自定义认证处理的过滤器,并加入到FilterChain的过程.在我们自己不在xml做特殊的配置情况下,security默认的做认证处理的过滤器为Usern ...
随机推荐
- JQuery中text(),html(),val()的区别
这3个都是jquery类库中的语法,分别是: text():获取或者改变指定元素的文本: html():获取或改变指定元素的html元素以及文本: val():获取或者改变指定元素的value值(一般 ...
- 8、Collaborative Metric Learning
一.摘要: 文章的核心思想:是如何把Metric learning 和 CF结合起来从而达到更好的推荐效果. 提出了CML(Collaborative Metric Learning),其学习一个联合 ...
- C语言基本语法——变量
1.变量作用域 2.局部变量 3.全局变量 4.变量生命周期 5.auto关键字 6.static关键字 1.变量作用域 • 变量作用域是指变量的有效范围 • 变量作用域是定义变量从何处被创建,到何处 ...
- HDU 1002 A + B Problem II( 高精度加法水 )
链接:传送门 题意:A + B 高精度,板子题 /************************************************************************* & ...
- uboot的readme导读
UBOOT的移植其实并没有想象中的难,这主要归功于众多的工程师已经将常见的平台代码写入了UBOOT,我们所要做的就是一点小小的更改,在网上看了很多相关的移植,也听到有人说其实看了UBOOT的readm ...
- 中山纪念中学培训杂题(难的都不在这里面qwq)
来中山纪中半个月了,差不多就要结束了, 写一些之前考试能更正的题解吧,还有一些不是给人做的(比如IOI2018互测.. 备注:我不会的就没有放上来了,所有数学有关的基本上都死了. 所以这里的题目都是相 ...
- SQL SERVER-集合操作
内连接 INNER JOIN(等值连接):只显示两个表中联结字段相等的行.这个和用select查询多表是一样的效果,所以很少用到:外连接:LEFT JOIN :以左表为基础,显示左表中的所有 ...
- Linux下基于多线程的echo
准备开始写一些Linux 下网络编程以及多线程的blog,就从这个简单的echo程序开始吧. 在echo的服务端使用多线程与客户进行通信,可以实现一个服务端程序同时连接多个客户的功能.那么,到底在服务 ...
- [cocos2dx笔记013]一个使用CCRenderTexture创建动态纹理显示数字的类
用CCLabelTTF显示的数字不好看.于是就想到用图片来代理.眼下网上的实现都是把每一个数字做一个CCSprite组合的方式. 可是我想.动态生成纹理的方式.没有就仅仅好自己手动写一个. 头文件 # ...
- HDU 4415 Assassin's Creed(贪心)
pid=4415">HDU 4415 题意: 壮哉我Assassin! E叔有一柄耐久度为m的袖剑,以及n个目标士兵要去解决. 每解决掉一个士兵,消耗袖剑Ai的耐久度.且获得该士兵的武 ...