关于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="certserver.pfx"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> </ItemGroup>
同理grpcclient.csproj 也要修改
<ItemGroup> <None Update="certclient.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的调用:
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