[英]C# Certificate Authentication with gRPC
我正在 C# 尝试 gRPC,并希望与 as.net core.Net 6 进行身份验证集成。我正在按照Microsoft 上的教程设置 gRPC 应用程序。
在我尝试添加身份验证之前,该应用程序没有任何问题。 我正在使用自签名证书,我已将其添加到我的本地用户存储以及我受信任的根存储中,以防证书因撤销而被拒绝。 我尝试了很多方法来帮助解决问题,但没有成功。 我不确定现在 go 在哪里,如果有任何指点/提示,我将不胜感激。
Kestrel Web 服务器 gRPC 文件
using Microsoft.AspNetCore.Authentication.Certificate;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;
using grpcServerTest.Services;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
namespace grpcServerTest
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Additional configuration is required to successfully run gRPC on macOS.
// For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682
// Add services to the container.
builder.Services.AddGrpc();
//builder.Services.AddAuthorization();
builder.Services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.AllowedCertificateTypes = CertificateTypes.All;
options.ValidateCertificateUse = false;
options.RevocationFlag = System.Security.Cryptography.X509Certificates.X509RevocationFlag.ExcludeRoot;
options.RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck;
options.Events = new CertificateAuthenticationEvents
{
OnChallenge = context =>
{
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
return Task.CompletedTask;
},
OnCertificateValidated = context =>
{
if (true)
{
var claims = new[]
{
new Claim(
ClaimTypes.NameIdentifier,
context.ClientCertificate.Subject,
ClaimValueTypes.String, context.Options.ClaimsIssuer),
new Claim(
ClaimTypes.Name,
context.ClientCertificate.Subject,
ClaimValueTypes.String, context.Options.ClaimsIssuer)
};
context.Principal = new ClaimsPrincipal(
new ClaimsIdentity(claims, context.Scheme.Name));
context.Success();
}
return Task.CompletedTask;
}
};
});
builder.Services.Configure<KestrelServerOptions>(options =>
{
options.ConfigureHttpsDefaults(options =>
{
options.SslProtocols = System.Security.Authentication.SslProtocols.Tls12;
options.CheckCertificateRevocation = false;
//options.ServerCertificate = GetClientCertificate();
options.ClientCertificateValidation = (cert, chain, errors) =>
{
Console.WriteLine("Client Validation Called");
errors = System.Net.Security.SslPolicyErrors.None;
return true;
};
});
});
var app = builder.Build();
app.UseCertificateForwarding();
app.UseAuthentication();
//app.UseAuthorization();
// Configure the HTTP request pipeline.
app.MapGrpcService<GreeterService>();
app.MapGet("/", () => "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");
app.Run();
}
}
}
gRPC 客户端代码
// See https://aka.ms/new-console-template for more information
using Grpc.Core;
using Grpc.Net.Client;
using GrpcTest;
using System.Security.Cryptography.X509Certificates;
internal class Program
{
private static async Task Main(string[] args)
{
Console.WriteLine("Hello, World!");
var x509 = GetClientCertificate();
var handler = new HttpClientHandler();
handler.SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls;
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ClientCertificates.Add(x509);
handler.UseProxy = false;
Console.ReadKey();
using var channel = GrpcChannel.ForAddress("https://localhost:7283", new GrpcChannelOptions()
{
HttpHandler = handler,
DisposeHttpClient = true
});
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
private static X509Certificate2 GetClientCertificate()
{
X509Store userCaStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
userCaStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificatesInStore = userCaStore.Certificates;
X509Certificate2Collection findResult = certificatesInStore.Find(X509FindType.FindBySubjectName, "grpctest", true);
X509Certificate2 clientCertificate = null!;
if (findResult.Count == 1)
{
clientCertificate = findResult[0];
}
else
{
throw new Exception("Unable to locate the correct client certificate.");
}
return clientCertificate;
}
catch
{
throw;
}
finally
{
userCaStore.Close();
}
}
}
这是 .NET 6 还是 7?
请参阅 https 中与 gRPC 和全链支持相关的部分:https://learn.microsoft.com/en-us/as.net/core/release-notes/as.netcore-7.0?view=as.netcore-7.0
使用 .NET 6 你可能需要使用类似https://github.com/MarkCiliaVincenti/TlsCertificateLoader
我是一个丁格斯。 我在请求中将公共证书传递给 HttpHandler,而不是实际执行身份验证的公钥和私钥。
这个问题,Kestrel 似乎一直在阻止证书,尽管我试图通过配置默认的 HTTPS 连接来绕过它。 一旦我在构建器中手动创建自己的侦听器并且不依赖默认配置,它似乎可以正常工作。
这是我用于我的构建器的代码,尽管可能有点过分,我不建议在不删除我的安全绕过的情况下将其用于生产。
builder.Services.Configure<KestrelServerOptions>(options => { options.Listen(IPAddress.Loopback, 8080, listenOptions => { listenOptions.UseConnectionLogging(); listenOptions.UseHttps(options => { options.ClientCertificateMode = ClientCertificateMode.RequireCertificate; options.CheckCertificateRevocation = false; options.AllowAnyClientCertificate(); options.ClientCertificateValidation = (cert, chain, errors) => { Console.WriteLine("Client Validation Called"); errors = System.Net.Security.SslPolicyErrors.None; return true; }; }); }); });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.