36 lines
2.0 KiB
C#
36 lines
2.0 KiB
C#
using System.Net.Http.Json;
|
||
using System.Security.Cryptography;
|
||
using System.Text;
|
||
using System.Text.Json;
|
||
using Microsoft.AspNetCore.Http;
|
||
using Microsoft.Extensions.Configuration;
|
||
|
||
namespace IM.InitCommon.Management;
|
||
|
||
public sealed class InternalClient(HttpClient http, IConfiguration config)
|
||
{
|
||
public async Task<T> Send<T>(string service, string path, object? body = null, CancellationToken ct = default)
|
||
{
|
||
var address = config[$"Management:Services:{service}"] ?? throw new InvalidOperationException($"未配置服务 {service}");
|
||
var key = config["Management:InternalKey"] ?? config["InternalApiKey"];
|
||
if (string.IsNullOrWhiteSpace(key)) throw new InvalidOperationException("未配置内部服务密钥");
|
||
using var request = new HttpRequestMessage(body is null ? HttpMethod.Get : HttpMethod.Post, new Uri(new Uri(address.TrimEnd('/') + "/"), path.TrimStart('/')));
|
||
request.Headers.Add("X-IM-Management-Key", key);
|
||
if (body is not null) request.Content = JsonContent.Create(body);
|
||
using var response = await http.SendAsync(request, ct);
|
||
if (!response.IsSuccessStatusCode) throw new InternalServiceException(service, (int)response.StatusCode);
|
||
return await response.Content.ReadFromJsonAsync<T>(cancellationToken: ct) ?? throw new InvalidOperationException("服务响应为空");
|
||
}
|
||
public static bool Authorized(HttpContext context)
|
||
{
|
||
var c = context.RequestServices.GetService(typeof(IConfiguration)) as IConfiguration;
|
||
var expected = c?["Management:InternalKey"] ?? c?["InternalApiKey"];
|
||
var actual = context.Request.Headers["X-IM-Management-Key"].ToString();
|
||
return !string.IsNullOrWhiteSpace(expected) && CryptographicOperations.FixedTimeEquals(SHA256.HashData(Encoding.UTF8.GetBytes(expected)), SHA256.HashData(Encoding.UTF8.GetBytes(actual)));
|
||
}
|
||
}
|
||
public sealed class InternalServiceException(string service, int status) : Exception($"{service} 服务请求失败({status})")
|
||
{
|
||
public int Status { get; } = status;
|
||
}
|