带入gRPC:对 RPC 方法做自定义认证

原文地址:带入gRPC:对 RPC 方法做自定义认证
项目地址:https://github.com/EDDYCJY/go...

前言

在前面的章节中,我们介绍了两种(证书算一种)可全局认证的方法:

  1. TLS 证书认证
  2. 基于 CA 的 TLS 证书认证
  3. Unary and Stream interceptor

而在实际需求中,常常会对某些模块的 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 方法做自定义认证的更多相关文章

  1. DRF认证、自定义认证和权限、自定义权限

    源码分析 """ 1)APIView的dispath(self, request, *args, **kwargs) 2)dispath方法内 self.initial( ...

  2. drf三大认证:认证组件-权限组件-权限六表-自定义认证组件的使用

    三大认证工作原理简介 认证.权限.频率 源码分析: from rest_framework.views import APIView 源码分析入口: 内部的三大认证方法封装: 三大组件的原理分析: 权 ...

  3. 跟我一起学Go系列:Go gRPC 安全认证方式-Token和自定义认证

    Go gRPC 系列: 跟我一起学Go系列:gRPC安全认证机制-SSL/TLS认证 跟我一起学 Go 系列:gRPC 拦截器使用 跟我一起学 Go 系列:gRPC 入门必备 接上一篇继续讲 gRPC ...

  4. gRPC【RPC自定义http2.0协议传输】

    gRPC 简介 gRPC是由Google公司开源的高性能RPC框架. gRPC支持多语言 gRPC原生使用C.Java.Go进行了三种实现,而C语言实现的版本进行封装后又支持C++.C#.Node.O ...

  5. asp.net core 自定义认证方式--请求头认证

    asp.net core 自定义认证方式--请求头认证 Intro 最近开始真正的实践了一些网关的东西,最近写几篇文章分享一下我的实践以及遇到的问题. 本文主要介绍网关后面的服务如何进行认证. 解决思 ...

  6. go微服务框架go-micro深度学习(四) rpc方法调用过程详解

    上一篇帖子go微服务框架go-micro深度学习(三) Registry服务的注册和发现详细解释了go-micro是如何做服务注册和发现在,服务端注册server信息,client获取server的地 ...

  7. go微服务框架go-micro深度学习 rpc方法调用过程详解

    摘要: 上一篇帖子go微服务框架go-micro深度学习(三) Registry服务的注册和发现详细解释了go-micro是如何做服务注册和发现在,服务端注册server信息,client获取serv ...

  8. Spring集成shiro做登陆认证

    一.背景 其实很早的时候,就在项目中有使用到shiro做登陆认证,直到今天才又想起来这茬,自己抽空搭了一个spring+springmvc+mybatis和shiro进行集成的种子项目,当然里面还有很 ...

  9. 【Spring Security】六、自定义认证处理的过滤器

    这里接着上一章的自定义过滤器,这里主要的是配置自定义认证处理的过滤器,并加入到FilterChain的过程.在我们自己不在xml做特殊的配置情况下,security默认的做认证处理的过滤器为Usern ...

随机推荐

  1. JQuery中text(),html(),val()的区别

    这3个都是jquery类库中的语法,分别是: text():获取或者改变指定元素的文本: html():获取或改变指定元素的html元素以及文本: val():获取或者改变指定元素的value值(一般 ...

  2. 8、Collaborative Metric Learning

    一.摘要: 文章的核心思想:是如何把Metric learning 和 CF结合起来从而达到更好的推荐效果. 提出了CML(Collaborative Metric Learning),其学习一个联合 ...

  3. C语言基本语法——变量

    1.变量作用域 2.局部变量 3.全局变量 4.变量生命周期 5.auto关键字 6.static关键字 1.变量作用域 • 变量作用域是指变量的有效范围 • 变量作用域是定义变量从何处被创建,到何处 ...

  4. HDU 1002 A + B Problem II( 高精度加法水 )

    链接:传送门 题意:A + B 高精度,板子题 /************************************************************************* & ...

  5. uboot的readme导读

    UBOOT的移植其实并没有想象中的难,这主要归功于众多的工程师已经将常见的平台代码写入了UBOOT,我们所要做的就是一点小小的更改,在网上看了很多相关的移植,也听到有人说其实看了UBOOT的readm ...

  6. 中山纪念中学培训杂题(难的都不在这里面qwq)

    来中山纪中半个月了,差不多就要结束了, 写一些之前考试能更正的题解吧,还有一些不是给人做的(比如IOI2018互测.. 备注:我不会的就没有放上来了,所有数学有关的基本上都死了. 所以这里的题目都是相 ...

  7. SQL SERVER-集合操作

    内连接      INNER JOIN(等值连接):只显示两个表中联结字段相等的行.这个和用select查询多表是一样的效果,所以很少用到:外连接:LEFT JOIN :以左表为基础,显示左表中的所有 ...

  8. Linux下基于多线程的echo

    准备开始写一些Linux 下网络编程以及多线程的blog,就从这个简单的echo程序开始吧. 在echo的服务端使用多线程与客户进行通信,可以实现一个服务端程序同时连接多个客户的功能.那么,到底在服务 ...

  9. [cocos2dx笔记013]一个使用CCRenderTexture创建动态纹理显示数字的类

    用CCLabelTTF显示的数字不好看.于是就想到用图片来代理.眼下网上的实现都是把每一个数字做一个CCSprite组合的方式. 可是我想.动态生成纹理的方式.没有就仅仅好自己手动写一个. 头文件 # ...

  10. HDU 4415 Assassin's Creed(贪心)

    pid=4415">HDU 4415 题意: 壮哉我Assassin! E叔有一柄耐久度为m的袖剑,以及n个目标士兵要去解决. 每解决掉一个士兵,消耗袖剑Ai的耐久度.且获得该士兵的武 ...