前言

随着.net core3.0的正式发布,gRPC服务被集成到了VS2019。本文主要演示如何对gRPC的服务进行认证授权。

分析

目前.net core使用最广的认证授权组件是基于OAuth2.0协议的IdentityServer4。而gRPC可以与ASP.NET Core Authentication一起使用来实现认证授权功能。本文将创建3个应用程序来完成gRPC的认证授权演示过程。

步骤

Ids4.Server

1.创建一个.net core的webapi
2.nuget引用最新的IdentityServer4的包
  1. <PackageReference Include="IdentityServer4" Version="3.0.1" />

IdentityServer4相关配置,因为是演示所以很简单,生产场景大家根据实际情况配置。

  1. namespace Ids4.Server
  2. {
  3. public class Config
  4. {
  5. public static IEnumerable<IdentityResource> GetIdentityResources()
  6. {
  7. return new List<IdentityResource>
  8. {
  9. new IdentityResources.OpenId(),
  10. new IdentityResources.Profile(),
  11. new IdentityResources.Email(),
  12. };
  13. }
  14. public static IEnumerable<ApiResource> GetApis()
  15. {
  16. return new List<ApiResource>
  17. {
  18. new ApiResource("api", "Demo API")
  19. {
  20. ApiSecrets = { new Secret("secret".Sha256()) }
  21. }
  22. };
  23. }
  24. public static IEnumerable<Client> GetClients()
  25. {
  26. return new List<Client>
  27. {
  28. new Client
  29. {
  30. ClientId = "client",
  31. ClientSecrets = { new Secret("secret".Sha256()) },
  32. AllowedGrantTypes = GrantTypes.ClientCredentials,
  33. AllowedScopes = { "api" },
  34. },
  35. };
  36. }
  37. }
  38. }
4. startup.cs 注入服务
  1. services.AddIdentityServer().AddInMemoryApiResources(Config.GetApis())
  2. .AddInMemoryIdentityResources(Config.GetIdentityResources())
  3. .AddInMemoryClients(Config.GetClients())
  4. .AddDeveloperSigningCredential(persistKey: false);
5. startup.cs 配置http请求管道
  1. app.UseIdentityServer();
6. 启动服务,使用PostMan进行调试,有返回结果表示服务创建成功
  1. POST /connect/token HTTP/1.1
  2. Host: localhost:5000
  3. Content-Type: application/x-www-form-urlencoded
  4. grant_type=client_credentials&client_id=client1&client_secret=secret

  1. {
  2. "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IlVyMmxuM2EwNGhWaGdDdWZTVTNtZVEiLCJ0eXAiOiJhdCtqd3QifQ.eyJuYmYiOjE1NzEzMDkwMTMsImV4cCI6MTU3MTMxMjYxMywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjoiYXBpIiwiY2xpZW50X2lkIjoiY2xpZW50Iiwic2NvcGUiOlsiYXBpIl19.X4pg9_FbPbWZl814XC0NYWTslfhMG4aXWEyXLrXhIojPJaL7Qvq9ieDF4S7x0psRcClwbwCg81hTrG3j2Cmcl0nzj_Ic7UY8MfN0dvAuy_fJdUf76TX0oOpir3SxgC8gnfaKyEoWmmbIyvwicWbKp9PP-EeTxG6-oMYn6PO22cwRVHDD28ZdEAq2DEkATOh9XPavoi9vGZhPQ1nviKL1K6tcYUGXSQbhWI9ISEqnTHqMX1xA_gcDIAplGvquXmtXdgyTsRoGolEtzDAYVH4sGUb1SpYx2nc8bgl6Qw27fhe0Uy9MR70kQMcEkCTdXLivjYjkuI9_quUyJHzdi5KgnQ",
  3. "expires_in": 3600,
  4. "token_type": "Bearer",
  5. "scope": "api"
  6. }

本篇不对IdentityServer4做更多的讲解,大家可以参考官方文档了解更多。

Grpc.Server

1. 使用vs2019创建gRPC服务端。

2. 不用做任何更改,直接使用默认创建的gRPC服务

Grpc.Client

1. 创建一个控制台程序
2. 引入nuget安装包
  1. <PackageReference Include="Google.Protobuf" Version="3.10.0" />
  2. <PackageReference Include="Grpc.Net.Client" Version="2.23.2" />
  3. <PackageReference Include="Grpc.Tools" Version="2.24.0">
  4. <PrivateAssets>all</PrivateAssets>
  5. <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  6. </PackageReference>

这3个核心包是客户端必备的,其中grpc.tools帮我们把proto文件转化成C#代码。

3. 创建Protos文件夹
4. 复制Grpc.Server项目Protos文件夹下的greet.proto文件到本项目的Protos文件夹
5. greet.proto文件右键设置gGRC Stub Classes为Client only。



也可以直接使用在项目文件里面代码设置如下:

  1. <ItemGroup>
  2. <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
  3. </ItemGroup>
6. gRPC客户端访问服务端代码
  1. var channel = GrpcChannel.ForAddress("https://localhost:5001");
  2. var client = new Greeter.GreeterClient(channel);
  3. var response = client.SayHello(new HelloRequest { Name = "World" });
  4. Console.WriteLine(response.Message);

启动gRPC服务端,在启动gRPC客户端控制台打印hello word表示成功。



identityServer接入gRPC是非常容易,和传统webapi差不多。

改造Grpc.Server支持IdentityServer4

1. 引入nuget包
  1. <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
2. startup.cs 注入服务,和IdentityServer4一样。
  1. services.AddGrpc(x => x.EnableDetailedErrors = false);
  2. services.AddAuthorization();
  3. services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
  4. .AddIdentityServerAuthentication(options =>
  5. {
  6. options.Authority = "http://localhost:5000";
  7. options.RequireHttpsMetadata = false;
  8. });
3. startup.cs 配置http请求管道
  1. if (env.IsDevelopment())
  2. {
  3. app.UseDeveloperExceptionPage();
  4. }
  5. app.UseRouting();
  6. app.UseAuthentication();
  7. app.UseAuthorization();
  8. app.UseEndpoints(endpoints =>
  9. {
  10. endpoints.MapGrpcService<GreeterService>();
  11. endpoints.MapGet("/", async context =>
  12. {
  13. await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
  14. });
  15. });
4. 对需要授权的服务打标签[Authorize],可以打在类上也可以打在方法上
  1. [Authorize]
  2. public class GreeterService : Greeter.GreeterBase
  3. {
  4. }

这个时候我们启动Grpc.Client访问Grpc.Server服务



发现报错401。说明此服务需要携带令牌才能访问。

改造Grpc.Client携带令牌访问

  1. //获取token可以直接使用HttpClient来获取,这里使用IdentityModel来获取token
  2. var httpClient = new HttpClient();
  3. var disco = await httpClient.GetDiscoveryDocumentAsync("http://localhost:5000");
  4. if (!disco.IsError)
  5. {
  6. var token = await httpClient.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest()
  7. {
  8. Address = disco.TokenEndpoint,
  9. ClientId = "client",
  10. ClientSecret = "secret"
  11. });
  12. var tokenValue = "Bearer " + token.AccessToken;
  13. var metadata = new Metadata
  14. {
  15. { "Authorization", tokenValue }
  16. };
  17. var callOptions = new CallOptions(metadata);
  18. var channel = GrpcChannel.ForAddress("https://localhost:5001");
  19. var client = new Greeter.GreeterClient(channel);
  20. var response = client.SayHello(new HelloRequest { Name = "World" }, callOptions);
  21. Console.WriteLine(response.Message);
  22. }

执行程序返回hello world表示成功。

传统调用webapi把token放到Header头的Authorization属性里面,grpc是放到Metadata里面,调用方法的时候传入CallOptions。使用上大同小异。

后记

目前gRPC各个语言的支持都已经很完善,因为跨语言,性能更高的特性非常适合做内网的通信。笔者也将继续对gRPC进行跟进,会尝试将部分的内部服务改造成gRPC,关于gRPC的相关问题也可以留言大家一起讨论。

源代码地址:github

.net core gRPC与IdentityServer4集成认证授权的更多相关文章

  1. 阶段5 3.微服务项目【学成在线】_day18 用户授权_10-前端集成认证授权-需求分析

    4 前端集成认证授权 4.1 需求分析 截至目前认证授权服务端的功能已基本完成,本章实现前端集成认证授权功能. 前端集成认证授权功能需要作如下工作: 1.前端页面校验用户的身份,如果用户没有登录则跳转 ...

  2. Django 中自定义用户模型及集成认证授权功能总结

    1. 概述 Django 中的 django.contrib.auth 应用提供了完整的用户及认证授权功能. Django 官方推荐基于内置 User 数据模型创建新的自定义用户模型,方便添加 bir ...

  3. 【ASP.NET Core学习】使用JWT认证授权

    概述 认证授权是很多系统的基本功能 , 在以前PC的时代 , 通常是基于cookies-session这样的方式实现认证授权 , 在那个时候通常系统的用户量都不会很大, 所以这种方式也一直很好运行, ...

  4. IdentityServer4身份认证授权入门

    一.简介 IdentityServer4 是为ASP.NET Core 系列量身打造的一款基于 OpenID Connect 和 OAuth 2.0 认证框架 特点: 1.认证服务 2.单点登录登出( ...

  5. 阶段5 3.微服务项目【学成在线】_day18 用户授权_11-前端集成认证授权-身份校验

    把下面赋值到nginx中 前端的服务需要配置一下 重启nginx 启动教学管理的前端 没有登陆直接就进来教学管理的后端了 下面我们要做的就是这两件事 1.前端页面校验用户的身份,如果用户没有登录则跳转 ...

  6. .NetCore下使用IdentityServer4 & JwtBearer认证授权在CentOS Docker容器中运行遇到的坑及填坑

    今天我把WebAPI部署到CentOS Docker容器中运行,发现原有在Windows下允许的JWTBearer配置出现了问题 在Window下我一直使用这个配置,没有问题 services.Add ...

  7. 阶段5 3.微服务项目【学成在线】_day18 用户授权_12-前端集成认证授权-携带JWT授权

    携带JWT授权 登陆后jwt已经存到了sessionStorage里面 当进行微服务的请求就要携带令牌.我们在拦截器里面做文章. 在axios的intercepters拦截器上 手工的给这个课程 造一 ...

  8. .net core 学习小结之 JWT 认证授权

    新增配置文件 { "Logging": { "IncludeScopes": false, "Debug": { "LogLeve ...

  9. .Net Core3.0使用gRPC 和IdentityServer4

    gRPC是什么gRPC是可以在任何环境中运行的现代开源高性能RPC框架.它可以通过可插拔的支持来有效地连接数据中心内和跨数据中心的服务,以实现负载平衡,跟踪,运行状况检查和身份验证.它也适用于分布式计 ...

随机推荐

  1. Spring boot 集成 Druid 数据源

    Druid是阿里开源的一个JDBC应用组件,其中包括三部分: DruidDriver:代理Driver,能够提供基于Filter-Chain模式的插件体系. DruidDataSource:高效可管理 ...

  2. C++ 深入浅出工厂模式(初识篇)

    初识工厂模式 我们先看工厂模式的介绍 这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创 ...

  3. Android Q 正式命名为 Android 10

    根据官方博文,谷歌已经公布了 Android Q 的名称,它并不是想以前一样,以甜食命名,也不是以任何以字母 Q 开头来命名,而是简单称它为 Android 10. 该公司表示,它正在改变其发布版本的 ...

  4. centos 7 ifconfig无法找到命令的方法

    场景:新安装centos   没有安装. centos7.2的mini版没有安装这个东东,所以我们就直接安装就好了,在终端里面输入: yum -y install net-tools

  5. Winform中怎样根据Name获取同窗体的控件

    场景 在同一个Winform窗体中,点击一个Button按钮时, 获取同窗体的其他控件的属性. 首先需要对要获取的控件赋予Name属性,然后就可以通过Name进行获取. 实现 在Button的点击事件 ...

  6. Java面试-容器的遍历

    当我们用增强for循环遍历非并发容器(HashMap.ArrayList等),如果修改其结构,会抛出异常ConcurrentModificationException,因此在阿里巴巴的Java规范中有 ...

  7. 2019-2020-1 20199314 <Linux内核原理与分析>第一周作业

    前言 本周对实验楼的Linux基础入门进行了学习,目前学习到实验九完成到挑战二. 学习和实验内容 快速学习了Linux系统的发展历程及其简介,学习了下的变量.用户权限管理.文件打包及压缩.常用命令的和 ...

  8. 安装vue-cli 3.

    安装node.js,查看版本node -v 修改npm为阿里的镜像源 npm install cnpm -g --registry=https://registry.npm.taobao.org 查看 ...

  9. 转:怎么用Sql语句获取一个数据库中的所有表的名字

    用sql获取数据库中所有的表名的方法:1.oracle下:select table_name from all_tables;2.MySQL下:select table_name from infor ...

  10. connection pool exhausted

    1.发现问题 生产环境发现有一些redis报错日志 connection pool exhausted.如果redis中没有数据 就直接回源 查DB.暂时不会有什么大问题.中文意思是连接池耗尽. 2. ...