asp.ner core 5.0 Grpc双向认证 和 restful api包装 外加swagger启用【VSCode创建】
关于grpc 我以前的文章 .Net Core3.0使用gRPC 和IdentityServer4 已经很向详细了, 关于http的双向认证 也已经有了, 大家可以参考 asp.net 5.0 https的双向认证(windows和ubuntu) ,今天主要试一下 在vccode 里面怎么完成全部的操作,证书还是用asp.net 5.0 https的双向认证(windows和ubuntu) 里面的, 在。net里面也有httpApi。本文主要是实现
1.gprc 客服端 和服务端 实现双向认证
2.普通的js 可以访问grpc服务, 这里采用httpapi 来包装【以前在go里面没有完全实现,在go里面用gateway后,grprc 客户端 和gateway 都只能用http协议, 不能像本文中 兼容https 和http】
Grpc Server
1.创建grpc server
创建结果如图:
2.现在我们创建grpcclient【 控制台程序】, 然后把cert文件夹拷贝到项目文件夹中,cert包含server.pfx和client.pfx证书
3. grpcserver项目需要用到server.pfx证书,grpcclient需要用到client.pfx证书 ,我习惯用相对目录,所以把证书拷贝到输出目录
用记事本修改grpcserver.csproj文件,添加
<ItemGroup> <None Update="cert\server.pfx"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> </ItemGroup>
同理grpcclient.csproj 也要修改
<ItemGroup> <None Update="cert\client.pfx"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> </ItemGroup>
4.修改grpcserver的Program.cs的CreateHostBuilder方法 需要添加引用:
using System.Security.Cryptography.X509Certificates; using Microsoft.AspNetCore.Server.Kestrel.Https; using System.Security.Authentication; //////////////////////////////////////////// public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); webBuilder.ConfigureKestrel(kerstrel => { kerstrel.ConfigureHttpsDefaults(https => { var serverPath = AppDomain.CurrentDomain.BaseDirectory + "cert\\server.pfx"; var serverCertificate = new X509Certificate2(serverPath, "123456789"); https.ServerCertificate = serverCertificate; https.ClientCertificateMode = ClientCertificateMode.AllowCertificate; https.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls | SslProtocols.None | SslProtocols.Tls11; https.ClientCertificateValidation = (cer, chain, error) => { return chain.Build(cer); }; }); }); });
5 注意系统的版本, 我在win7下面 有如下错误HTTP/2 over TLS is not supported on Windows versions earlier than Windows 10 and Windows Server 2016 due to incompatible ciphers or missing ALPN support.现在修改grpcclient,将服务端的Protos/greet.proto拷贝到客户端Protos/greet.proto下,并在grpcclient.csproj项目文件中添加元素项组
客服端 代码:
static void Main(string[] args) { var handler = new HttpClientHandler() { SslProtocols = SslProtocols.Tls12, ClientCertificateOptions = ClientCertificateOption.Manual, ServerCertificateCustomValidationCallback = (message, cer, chain, errors) => { return chain.Build(cer); } }; var path = AppDomain.CurrentDomain.BaseDirectory + "cert\\client.pfx"; var crt = new X509Certificate2(path, "123456789"); handler.ClientCertificates.Add(crt); var channel = GrpcChannel.ForAddress("https://localhost:5001",new GrpcChannelOptions{HttpHandler=handler}); var client = new Greeter.GreeterClient(channel); var reply = client.SayHello( new HelloRequest { Name = "GreeterClient" }); Console.WriteLine("Greeting: " + reply.Message); }
运行结果:
gRPC HTTP API
1.在grpcserver 添加 Microsoft.AspNetCore.Grpc.HttpApi
2.Startup.cs 添加 ConfigureServices方法 添加 services.AddGrpcHttpApi();
3.添加 google/api/http.proto ,google/api/annotations.proto和 google/protobuf/descriptor.proto 到 grpcserver【注意google 文件和Protos文件夹同级别】
4.修改greet.proto 如下: 主要是添加 import "google/api/annotations.proto"; 引用 和 api定义 option (google.api.http) = { get: "/v1/greeter/{name}" };
syntax = "proto3"; import "google/api/annotations.proto"; option csharp_namespace = "grpcserver"; package greet; // The greeting service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) { option (google.api.http) = { get: "/v1/greeter/{name}" }; } } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings. message HelloReply { string message = 1; }
启用 Swagger/OpenAPI
1.添加引用 Microsoft.AspNetCore.Grpc.Swagger.
2.修改 Startup.cs 文件
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.OpenApi.Models; namespace grpcserver { public class Startup { // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { services.AddGrpc(); services.AddGrpcHttpApi(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); }); services.AddGrpcSwagger(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); }); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGrpcService<GreeterService>(); endpoints.MapGet("/", async context => { 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"); }); }); } } }
运行服务端:访问 https://localhost:5001/swagger/index.html
修改grpcserver 让他支持https 双向认证 同时也支持普通http 请求
修改grpcserver的Program.cs的CreateHostBuilder 方法如下:
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); webBuilder.ConfigureKestrel(kerstrel => { kerstrel.Listen(IPAddress.Any, 5000, o => o.Protocols = HttpProtocols.Http1AndHttp2); kerstrel.Listen(IPAddress.Any, 5001, listenOptions => { var serverPath = AppDomain.CurrentDomain.BaseDirectory + "cert\\server.pfx"; var serverCertificate = new X509Certificate2(serverPath, "123456789"); var httpsConnectionAdapterOptions = new HttpsConnectionAdapterOptions() { ClientCertificateMode = ClientCertificateMode.AllowCertificate, SslProtocols = System.Security.Authentication.SslProtocols.Tls12, //用chain.Build验证客户端证书 ClientCertificateValidation = (cer, chain, error) => { return chain.Build(cer); }, ServerCertificate = serverCertificate }; listenOptions.UseHttps(httpsConnectionAdapterOptions); }); }); });
修改grpcclient的调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | static void Main( string [] args) { var handler = new HttpClientHandler() { SslProtocols = SslProtocols.Tls12, ClientCertificateOptions = ClientCertificateOption.Manual, ServerCertificateCustomValidationCallback = (message, cer, chain, errors) => { return chain.Build(cer); } }; var path = AppDomain.CurrentDomain.BaseDirectory + "cert\\client.pfx" ; var crt = new X509Certificate2(path, "123456789" ); handler.ClientCertificates.Add(crt); var channel = GrpcChannel.ForAddress( "https://localhost:5001" , new GrpcChannelOptions{HttpHandler=handler}); var client = new Greeter.GreeterClient(channel); var reply = client.SayHello( new HelloRequest { Name = "GreeterClient" }); Console.WriteLine( "Greeting: " + reply.Message); /// Console.WriteLine( "http start................" ); var httphandler = new HttpClientHandler(); httphandler.ServerCertificateCustomValidationCallback=HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; var httpclient= new HttpClient(httphandler); var ret= httpclient.GetStringAsync( "http://localhost:5000/v1/greeter/gavin" ).Result; Console.WriteLine(ret); } 点击并拖拽以移动 |
运行结果:
文件下载:https://download.csdn.net/download/dz45693/14015673 https://github.com/dz45693/asp.netgrpccert.git
参考
https://docs.microsoft.com/en-us/aspnet/core/grpc/httpapi?view=aspnetcore-5.0
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?