问题描述
我正在寻找一些反馈或指导。我已经在dotnet core 3.1中构建了grpc服务器和客户端。仅此客户端将与服务器通信,但仍需要保护服务器端点。我正在尝试对其实施身份验证安全性,而jwt承载令牌似乎是一条不错的路径。我正在尝试遵循示例here(来自此MS Doc),该示例看似非常简单,但由于任何人都可以访问generate令牌端点,因此似乎对生产使用不安全。我认为它可以修改和实现在get令牌请求上传递的共享机密。这似乎是个好方法还是其他想法?
除了这一部分,我还有一个我不太了解的关于客户端代码的问题。在客户端启动时,它通过调用CreateAuthenticatedChannel()建立一个grpc通道,该通道似乎仅在设置了_token时添加承载令牌。在客户端启动并点击第三个数字之前,您不会获得令牌,但是我看不到通道或客户端在何处重建以包含元数据令牌值。该示例似乎可以工作,但不了解。
class Program
{
// The port number(5001) must match the port of the gRPC server.
private const string Address = "localhost:5001";
private static string _token;
static async Task Main(string[] args)
{
var channel = CreateAuthenticatedChannel($"https://{Address}");
var client = new Ticketer.TicketerClient(channel);
Console.WriteLine("gRPC Ticketer");
Console.WriteLine();
Console.WriteLine("Press a key:");
Console.WriteLine("1: Get available tickets");
Console.WriteLine("2: Purchase ticket");
Console.WriteLine("3: Authenticate");
Console.WriteLine("4: Exit");
Console.WriteLine();
var exiting = false;
while (!exiting)
{
var consoleKeyInfo = Console.ReadKey(intercept: true);
switch (consoleKeyInfo.KeyChar)
{
case '1':
await GetAvailableTickets(client);
break;
case '2':
await PurchaseTicket(client);
break;
case '3':
_token = await Authenticate();
break;
case '4':
exiting = true;
break;
}
}
Console.WriteLine("Exiting");
}
private static GrpcChannel CreateAuthenticatedChannel(string address)
{
var credentials = CallCredentials.FromInterceptor((context,Metadata) =>
{
if (!string.IsNullOrEmpty(_token))
{
Metadata.Add("Authorization",$"Bearer {_token}");
}
return Task.CompletedTask;
});
// SslCredentials is used here because this channel is using TLS.
// Channels that aren't using TLS should use ChannelCredentials.Insecure instead.
var channel = GrpcChannel.ForAddress(address,new GrpcChannelOptions
{
Credentials = ChannelCredentials.Create(new SslCredentials(),credentials)
});
return channel;
}
private static async Task<string> Authenticate()
{
Console.WriteLine($"Authenticating as {Environment.UserName}...");
var httpClient = new HttpClient();
var request = new HttpRequestMessage
{
RequestUri = new Uri($"https://{Address}/generateJwtToken?name={HttpUtility.UrlEncode(Environment.UserName)}"),Method = HttpMethod.Get,Version = new Version(2,0)
};
var tokenResponse = await httpClient.SendAsync(request);
tokenResponse.EnsureSuccessstatusCode();
var token = await tokenResponse.Content.ReadAsstringAsync();
Console.WriteLine(token);
Console.WriteLine("Successfully authenticated.");
return token;
}
private static async Task PurchaseTicket(Ticketer.TicketerClient client)
{
Console.WriteLine("Purchasing ticket...");
try
{
var response = await client.BuyTicketsAsync(new BuyTicketsRequest { Count = 1 });
if (response.Success)
{
Console.WriteLine("Purchase successful.");
}
else
{
Console.WriteLine("Purchase Failed. No tickets available.");
}
}
catch (Exception ex)
{
Console.WriteLine("Error purchasing ticket." + Environment.NewLine + ex.ToString());
}
}
private static async Task GetAvailableTickets(Ticketer.TicketerClient client)
{
Console.WriteLine("Getting available ticket count...");
var response = await client.GetAvailableTicketsAsync(new Empty());
Console.WriteLine("Available ticket count: " + response.Count);
}
}
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)