热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

基与python的GRPCSSL/TLS加密及Token鉴权

目录结构.├──protos│└──hello_world.proto├──dists│├──__init__.py│├──hello_world_

基与python的GRPC SSL/TLS加密及Token鉴权

目录结构

.
├── protos
│   └── hello_world.proto
├── dists
│   ├── __init__.py
│   ├── hello_world_pb2.py
│   └── hello_world_pb2_grpc.py
├── server.py
├── client.py
├── token.py
├── grpc_ssl_key.pem
├── grpc_ssl_cert.pem
└── grpc_ssl_server.pem

 构建protobuf

# protos/hello_world.proto

syntax = "proto3";

package test;

message User {
    string name = 1;
}

message Result {
    string reply = 1;
}

service Test {
    rpc Hello(User) returns (Result) {}
}

# 通过命令构建
python -m grpc_tools.protoc 
  -I protos 
  --python_out=dists 
  --grpc_python_out=dists 
  protos/hello_world.proto

 SSL/TLS加密

创建密钥

1 // 创建grpc_ssl_key.pem和grpc_ssl_cert.pem
2 // 其中务必事先指定, 后续需要用到
3 openssl req -subj "/CN=black-ip.yazx.com" -x509 -newkey rsa:4096 -days 7200 
4     -keyout grpc-ssl-key.pem 
5     -out grpc-ssl-cert.pem
6 // 创建grpc_ssl_server.pem
7 openssl rsa -in grpc-ssl-key.pem -out grpc-ssl-server.pem

 服务端加载密钥

# server.py

from grpc.experimental import aio
from typing import AnyStr
from dist import hello_world_pb2
from dist import hello_world_pb2_grpc

# 实现具体的grpc函数
class TestServicer(hello_world_pb2_grpc.TestServicer):

    async def Hello(self, request, context) -> hello_world_pb2.Result:
        return hello_world_pb2.Result(reply=f"hello {request.name}")

# 读取密钥二进制数据
def read_file(path: str, binary: bool) -> AnyStr:
    with open(path, "rb" if binary else "r") as f:
        return f.read()

# 创建grpc服务端证书
def create_ssl_server_credentials() -> aio.grpc.ChannelCredentials:
    return aio.grpc.ssl_server_credentials(
        private_key_certificate_chain_pairs=(
            (
                read_file("grpc_ssl_server.pem", True),
                read_file("grpc_ssl_cert.pem", True),
            ),
        )
    )

# 运行grpc服务
async def run(host: str, port: int) -> None:
    server = aio.server()
    server_credetials = create_ssl_server_credentials()
    server.add_secure_port(f"[::]:{port}", server_credetials)
    hello_world_pb2_grpc.add_TestServicer_to_server(TestServicer(), server)
    await server.start()
    await server.wait_for_termination()

 客户端加载密钥

# client.py

from grpc.experimental import aio
from typing import AnyStr
from dist import hello_world_pb2
from dist import hello_world_pb2_grpc

# 创建grpc客户端证书
def create_ssl_channel_credentials() -> aio.grpc.ChannelCredentials:
    return aio.grpc.ssl_channel_credentials(
        root_certificates=read_file("grpc_ssl_cert.pem")
    )

# 运行grpc客户端
async def run(host: str, port: int) -> None:
    options = (("grpc.ssl_target_name_override", ""),)
    kwargs = {
        "target": f"{host}:{port}",
        "options": (
            ("grpc.lb_policy_name", "round_robin"),  # 自动根据dns域名解析服务列表
            *options
        )
    }
    channel_credentials = create_ssl_channel_credentials()
    creds = aio.grpc.composite_channel_credentials(channel_credentials)
    channel = aio.secure_channel(**kwargs, credentials=creds)
    await channel.channel_ready()
    stub = hello_world_pb2_grpc.TestStub(channel)
    result = await stub.Hello(hello_world_pb2.User(name="world"))

 Token鉴权

grpc强制Token鉴权必须使用SSL/TLS加密

 实现Token校验

# token.py

from typing import Callable, List, Any
from grpc.experimental import aio

class BearerToken(object):
    code: aio.grpc.StatusCode = aio.grpc.StatusCode.UNAUTHENTICATED
    details: str = "bad bearer token"

    def __init__(self, token: str) -> None:
        self.token = token

    def __call__(self, func) -> Callable:
        async def wrapper(inner_self, request, context: aio.ServicerContext) -> Any:
            metadata = context.invocation_metadata()
            for item in metadata:
                if item[0] == "authorization" and item[1] == f"Bearer {self.token}":
                    return await func(inner_self, request, context)
            await context.abort(
                code=self.code,
                details=self.details,
                trailing_metadata=metadata
            )

        return wrapper

 服务端校验Token

# server.py

from grpc.experimental import aio
from typing import AnyStr
from dist import hello_world_pb2
from dist import hello_world_pb2_grpc
from token import BearerToken

# 实现具体的grpc函数
class TestServicer(hello_world_pb2_grpc.TestServicer):

    @BearerToken(token="xxx")
    async def Hello(self, request, context) -> hello_world_pb2.Result:
        return hello_world_pb2.Result(reply=f"hello {request.name}")

 客户端注入Token

# client.py

from grpc.experimental import aio

token = "xxx"

# 创建Token认证
def create_access_token_credentials(cls) -> aio.grpc.CallCredentials:
    return aio.grpc.access_token_call_credentials(token)

# 运行grpc客户端
async def run(host: str, port: int) -> None:
    options = (("grpc.ssl_target_name_override", ""),)
    kwargs = {
        "target": f"{host}:{port}",
        "options": (
            ("grpc.lb_policy_name", "round_robin"),  # 自动根据dns域名解析服务列表
            *options
        )
    }
    channel_credentials = create_ssl_channel_credentials()
    token_credentials = self.create_access_token_credentials()
    creds = aio.grpc.composite_channel_credentials(
        channel_credentials,
        token_credentials
    )
    channel = aio.secure_channel(**kwargs, credentials=creds)
    await channel.channel_ready()
    stub = hello_world_pb2_grpc.TestStub(channel)
    result = await stub.Hello(hello_world_pb2.User(name="world"))

 

 

 


推荐阅读
  • 1、获取类身上的成员变量--class_copyIvarListif([badgeViewChildisKindOfClass:NSClassFromString(_UIBadg ... [详细]
  • 序本文主要研究一下nacosServiceManager的removeInstanceServiceManagernacos-1.1.3namingsrcmainjavacomal ... [详细]
  • 如何查询zone下的表的信息
    本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • 图像因存在错误而无法显示 ... [详细]
  • Android实战——jsoup实现网络爬虫,糗事百科项目的起步
    本文介绍了Android实战中使用jsoup实现网络爬虫的方法,以糗事百科项目为例。对于初学者来说,数据源的缺乏是做项目的最大烦恼之一。本文讲述了如何使用网络爬虫获取数据,并以糗事百科作为练手项目。同时,提到了使用jsoup需要结合前端基础知识,以及如果学过JS的话可以更轻松地使用该框架。 ... [详细]
  • 加密、解密、揭秘
    谈PHP中信息加密技术同样是一道面试答错的问题,面试官问我非对称加密算法中有哪些经典的算法?当时我愣了一下,因为我把非对称加密与单项散列加 ... [详细]
  • Day 5 20190120 老男孩python学习第5天 内容整理
    今天继续看MasteringPycharm的视频,一个半小时看git的教学视频:视频1小时44分钟,看了2个半小时以上https:www.youtube ... [详细]
  • 突然觉得服务器ssh密码登录总是浪费一定量的时间,就想试试用sshKey进行登录。生成服务器sshkey和本地sshkey$ssh-keygen在服务器上生成一个authorize ... [详细]
  • 在实际的工作流业务开发中,当用户完成当前用户任务时,需要指定下一个用户任务的审核人。此时我们需要获取下一个节点的一些信息,来确定下一个用户任务的审核人有哪些。在实际工 ... [详细]
  • 本文整理了Java中com.atlassian.scheduler.config.JobConfig类的一些代码示例,展示了JobConfig ... [详细]
  • Lodash中文文档(v3.10.1)–“Collection”要领TranslatedbyPeckZegOriginalDocs:Lodashv3.10.1Docs乞助翻译文档的 ... [详细]
  • 历史指对人类社会过来的事件和流动,以及对这些事件行为有零碎的记录、钻研和诠释。历史是文化的传承,积攒和扩大,是人类文明的轨迹。APISpace的历史上的 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • 本文介绍了Windows Vista操作系统中的用户账户保护功能,该功能是为了增强系统的安全性而设计的。通过对Vista测试版的体验,可以看到系统在安全性方面的进步。该功能的引入,为用户的账户安全提供了更好的保障。 ... [详细]
author-avatar
mobiledu2502882517
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有