变更详情摘要:
- 功能增强 : - AliSslProvider.cs :实现了从阿里云获取证书列表及删除过期证书的逻辑。 - TencentSslProvider.cs :增加了腾讯云过期证书的清理功能。 - ISslDownloadProvider.cs :扩展了接口协议,并丰富了 SslCertificate 模型属性。 - 任务调度 : - Program.cs :集成了 SslDownloadJob 到 Quartz 框架中,支持自动化运行。 - 文档与规范 : - 对项目关键入口和 Provider 进行了全面的代码注释补全。
This commit is contained in:
@@ -0,0 +1,66 @@
|
|||||||
|
{
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"pgConnection": "Host=127.0.0.1;Port=5432;Database=Worker;Username=Worker;Password=123456;"
|
||||||
|
},
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"App": {
|
||||||
|
"GetIpv4Url": "http://47.108.74.59:8001/api/NetWork/GetIp",
|
||||||
|
"AppJob": {
|
||||||
|
"Corn": "0/5 * * * * ?" //https://cron.qqe2.com/
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DDNS": {
|
||||||
|
"Platform": 2, //1 Ali 2 Tencent 3 Namesilo
|
||||||
|
// 主域名
|
||||||
|
"Domain": "we965.cn",
|
||||||
|
// 子域名前缀
|
||||||
|
"SubDomainArray": [ "mp", "git", "webutil", "dev", "sftp" ],
|
||||||
|
// 记录类型
|
||||||
|
"type": "A",
|
||||||
|
//间隔时间 秒
|
||||||
|
"time": "30"
|
||||||
|
},
|
||||||
|
"SslDownload": {
|
||||||
|
"Enabled": true,
|
||||||
|
"Corn": "0/5 * * * * ?", //https://cron.qqe2.com/
|
||||||
|
"Platform": 2,
|
||||||
|
"SavePath": "D:\\Paths\\ssl",
|
||||||
|
"ExpireDays": 5,
|
||||||
|
"DownloadItems": [
|
||||||
|
{
|
||||||
|
"Domain": "git.we965.cn",
|
||||||
|
"FileName": "git.we965.cn.pem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "webutil.we965.cn",
|
||||||
|
"FileName": "webutil.we965.cn.pem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "dev.we965.cn",
|
||||||
|
"FileName": "dev.we965.cn.pem"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"TencentCloud": {
|
||||||
|
"SecretId": "AKIDy35008NYm6T1v3R3gGtU1UIHOe0NizON",
|
||||||
|
"SecretKey": "1sXQmASfmmlwAXuDh8fVYUOLI7mJagbQ",
|
||||||
|
"Region": "ap-guangzhou",
|
||||||
|
"Dnspod": {
|
||||||
|
"Endpoint": "dnspod.tencentcloudapi.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AliCloud": {
|
||||||
|
"AccessKeyId": "1111",
|
||||||
|
"AccessKeySecret": "1111",
|
||||||
|
"RegionId": "cn-hangzhou",
|
||||||
|
"Endpoint": "1111"
|
||||||
|
},
|
||||||
|
"Namesilo": {
|
||||||
|
"ApiKey": "1111"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 17
|
|
||||||
VisualStudioVersion = 17.2.32616.157
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hua.DDNS", "Hua.DDNS\Hua.DDNS.csproj", "{EBC77B5D-87D5-4923-84A6-93DB2248DEB0}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hua.DDNS.Test", "Hua.DDNS.Test\Hua.DDNS.Test.csproj", "{BB544060-5ABF-4A3C-965B-BE7CA7BD61E7}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{EBC77B5D-87D5-4923-84A6-93DB2248DEB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{EBC77B5D-87D5-4923-84A6-93DB2248DEB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{EBC77B5D-87D5-4923-84A6-93DB2248DEB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{EBC77B5D-87D5-4923-84A6-93DB2248DEB0}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{BB544060-5ABF-4A3C-965B-BE7CA7BD61E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{BB544060-5ABF-4A3C-965B-BE7CA7BD61E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{BB544060-5ABF-4A3C-965B-BE7CA7BD61E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{BB544060-5ABF-4A3C-965B-BE7CA7BD61E7}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {D8744CA6-C2DB-4287-B8B3-E5917B12391D}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<Solution>
|
||||||
|
<Project Path="Hua.DDNS.Test/Hua.DDNS.Test.csproj" />
|
||||||
|
<Project Path="Hua.DDNS/Hua.DDNS.csproj" />
|
||||||
|
</Solution>
|
||||||
@@ -1,10 +1,28 @@
|
|||||||
namespace Hua.DDNS.Common.Config.Options
|
namespace Hua.DDNS.Common.Config.Options
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 阿里云配置选项
|
||||||
|
/// </summary>
|
||||||
public class AliCloudOption
|
public class AliCloudOption
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 访问密钥 ID
|
||||||
|
/// </summary>
|
||||||
public string AccessKeyId { get; set; }
|
public string AccessKeyId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 访问密钥私钥
|
||||||
|
/// </summary>
|
||||||
public string AccessKeySecret { get; set; }
|
public string AccessKeySecret { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 区域 ID (如 cn-hangzhou)
|
||||||
|
/// </summary>
|
||||||
public string RegionId { get; set; }
|
public string RegionId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 访问端点 (可选)
|
||||||
|
/// </summary>
|
||||||
public string Endpoint { get; set; }
|
public string Endpoint { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
using Hua.DDNS.DDNSProviders;
|
using Hua.DDNS.DDNSProviders;
|
||||||
|
|
||||||
namespace Hua.DDNS.Common.Config.Options
|
namespace Hua.DDNS.Common.Config.Options
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// app configuration class
|
/// 应用程序全局配置类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AppOption
|
public class AppOption
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// domain configuration
|
/// DDNS 相关配置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DdnsOption DDNS { get; set; }
|
public DdnsOption DDNS { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -7,17 +7,17 @@ using System.Threading.Tasks;
|
|||||||
namespace Hua.DDNS.Common.Config.Options
|
namespace Hua.DDNS.Common.Config.Options
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// DDNS Platform
|
/// DDNS 平台类型枚举
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum PlatformEnum
|
public enum PlatformEnum
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ali
|
/// 阿里云
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Ali = 1,
|
Ali = 1,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tencent
|
/// 腾讯云
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Tencent,
|
Tencent,
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,69 @@
|
|||||||
namespace Hua.DDNS.Common.Config.Options
|
namespace Hua.DDNS.Common.Config.Options
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// SSL 证书来源平台枚举
|
||||||
|
/// </summary>
|
||||||
public enum SslPlatformEnum
|
public enum SslPlatformEnum
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 阿里云
|
||||||
|
/// </summary>
|
||||||
Ali = 1,
|
Ali = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// 腾讯云
|
||||||
|
/// </summary>
|
||||||
Tencent = 2
|
Tencent = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SSL 证书下载配置选项
|
||||||
|
/// </summary>
|
||||||
public class SslDownloadOption
|
public class SslDownloadOption
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 是否启用
|
||||||
|
/// </summary>
|
||||||
public bool Enabled { get; set; }
|
public bool Enabled { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cron 定时表达式
|
||||||
|
/// </summary>
|
||||||
public string Corn { get; set; }
|
public string Corn { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 云平台类型
|
||||||
|
/// </summary>
|
||||||
public SslPlatformEnum Platform { get; set; }
|
public SslPlatformEnum Platform { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 证书保存本地路径
|
||||||
|
/// </summary>
|
||||||
public string SavePath { get; set; }
|
public string SavePath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 过期天数阈值 (提前多少天开始下载更新)
|
||||||
|
/// </summary>
|
||||||
public int ExpireDays { get; set; }
|
public int ExpireDays { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 需要下载的证书列表
|
||||||
|
/// </summary>
|
||||||
public List<SslDownloadItem> DownloadItems { get; set; }
|
public List<SslDownloadItem> DownloadItems { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SSL 证书下载项详情
|
||||||
|
/// </summary>
|
||||||
public class SslDownloadItem
|
public class SslDownloadItem
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 域名
|
||||||
|
/// </summary>
|
||||||
public string Domain { get; set; }
|
public string Domain { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存到本地的文件名 (不含后缀)
|
||||||
|
/// </summary>
|
||||||
public string FileName { get; set; }
|
public string FileName { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,29 @@ using Hua.DDNS.DDNSProviders.Dnspod;
|
|||||||
|
|
||||||
namespace Hua.DDNS.Common.Config.Options
|
namespace Hua.DDNS.Common.Config.Options
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 腾讯云配置选项
|
||||||
|
/// </summary>
|
||||||
public class TencentCloudOption
|
public class TencentCloudOption
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 密钥 ID
|
||||||
|
/// </summary>
|
||||||
public string SecretId { get; set; }
|
public string SecretId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 密钥私钥
|
||||||
|
/// </summary>
|
||||||
public string SecretKey { get; set; }
|
public string SecretKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 区域 (如 ap-guangzhou)
|
||||||
|
/// </summary>
|
||||||
public string Region { get; set; }
|
public string Region { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dnspod 相关配置 (已并入腾讯云)
|
||||||
|
/// </summary>
|
||||||
public DnspodOption Dnspod { get; set; }
|
public DnspodOption Dnspod { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
using Hua.DDNS.Common.Config.Options;
|
using Hua.DDNS.Common.Config.Options;
|
||||||
|
|
||||||
namespace Hua.DDNS.Common.Config
|
namespace Hua.DDNS.Common.Config
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// this is a strongly-typed configuration provider
|
/// 强类型配置提供者,用于方便地访问应用程序配置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SettingProvider
|
public class SettingProvider
|
||||||
{
|
{
|
||||||
private readonly AppOption _app;
|
private readonly AppOption _app;
|
||||||
private readonly IConfiguration _configuration;
|
private readonly IConfiguration _configuration;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="configuration">配置对象</param>
|
||||||
public SettingProvider(IConfiguration configuration)
|
public SettingProvider(IConfiguration configuration)
|
||||||
{
|
{
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
@@ -17,6 +22,9 @@ namespace Hua.DDNS.Common.Config
|
|||||||
_configuration.GetSection("App").Bind(_app);
|
_configuration.GetSection("App").Bind(_app);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取应用程序配置选项
|
||||||
|
/// </summary>
|
||||||
public AppOption App => _app;
|
public AppOption App => _app;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
namespace Hua.DDNS.Common
|
namespace Hua.DDNS.Common
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 文件操作助手类
|
||||||
|
/// </summary>
|
||||||
public class FileHelper
|
public class FileHelper
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 如果文件存在则删除
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">文件路径</param>
|
||||||
public static void DeleteIfExists(string path)
|
public static void DeleteIfExists(string path)
|
||||||
{
|
{
|
||||||
if (File.Exists(path))
|
if (File.Exists(path))
|
||||||
|
|||||||
@@ -1,15 +1,23 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Hua.DDNS.Common.Http
|
namespace Hua.DDNS.Common.Http
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Http 请求助手类,用于执行各种 HTTP 请求
|
||||||
|
/// </summary>
|
||||||
public class HttpHelper: IHttpHelper
|
public class HttpHelper: IHttpHelper
|
||||||
{
|
{
|
||||||
private static ILogger<HttpHelper> _logger;
|
private static ILogger<HttpHelper> _logger;
|
||||||
private static HttpClientHandler _handler;
|
private static HttpClientHandler _handler;
|
||||||
private IConfiguration _configuration;
|
private IConfiguration _configuration;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">日志对象</param>
|
||||||
|
/// <param name="configuration">配置对象</param>
|
||||||
public HttpHelper(ILogger<HttpHelper> logger, IConfiguration configuration)
|
public HttpHelper(ILogger<HttpHelper> logger, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@@ -17,26 +25,30 @@ namespace Hua.DDNS.Common.Http
|
|||||||
_handler = new HttpClientHandler();
|
_handler = new HttpClientHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取 HttpClient 实例
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>HttpClient 实例</returns>
|
||||||
public HttpClient GetHttpClient()
|
public HttpClient GetHttpClient()
|
||||||
{
|
{
|
||||||
return new HttpClient(_handler){};
|
return new HttpClient(_handler){};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PostAsync
|
/// 异步执行 Post 请求并解析 JSON 结果
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TIn"></typeparam>
|
/// <typeparam name="TIn">输入数据类型</typeparam>
|
||||||
/// <typeparam name="TOut"></typeparam>
|
/// <typeparam name="TOut">输出结果类型</typeparam>
|
||||||
/// <param name="url"></param>
|
/// <param name="url">请求地址</param>
|
||||||
/// <param name="input"></param>
|
/// <param name="input">输入数据</param>
|
||||||
/// <param name="timeOut">超时时间</param>
|
/// <param name="timeOut">超时时间 (秒)</param>
|
||||||
/// <returns></returns>
|
/// <returns>解析后的结果对象</returns>
|
||||||
public async Task<TOut?> PostAsync<TIn, TOut>(string url, TIn input, int timeOut = 10)
|
public async Task<TOut?> PostAsync<TIn, TOut>(string url, TIn input, int timeOut = 10)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var client = GetHttpClient();
|
var client = GetHttpClient();
|
||||||
client.Timeout = new TimeSpan(0, 10, timeOut);
|
client.Timeout = TimeSpan.FromSeconds(timeOut);
|
||||||
_logger.LogDebug($"Post:{url}\n[{JsonConvert.SerializeObject(input)}]");
|
_logger.LogDebug($"Post:{url}\n[{JsonConvert.SerializeObject(input)}]");
|
||||||
var result = await client.PostAsync(url, JsonContent.Create(input));
|
var result = await client.PostAsync(url, JsonContent.Create(input));
|
||||||
var strResult = await result.Content.ReadAsStringAsync();
|
var strResult = await result.Content.ReadAsStringAsync();
|
||||||
@@ -55,18 +67,18 @@ namespace Hua.DDNS.Common.Http
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PostAsync
|
/// 异步执行 Get 请求并解析 JSON 结果
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TOut"></typeparam>
|
/// <typeparam name="TOut">输出结果类型</typeparam>
|
||||||
/// <param name="url"></param>
|
/// <param name="url">请求地址</param>
|
||||||
/// <param name="timeOut"></param>
|
/// <param name="timeOut">超时时间 (秒)</param>
|
||||||
/// <returns></returns>
|
/// <returns>解析后的结果对象</returns>
|
||||||
public async Task<TOut?> GetAsync<TOut>(string url,int timeOut = 10)
|
public async Task<TOut?> GetAsync<TOut>(string url,int timeOut = 10)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var client = GetHttpClient();
|
var client = GetHttpClient();
|
||||||
client.Timeout = new TimeSpan(0, 10, timeOut);
|
client.Timeout = TimeSpan.FromSeconds(timeOut);
|
||||||
_logger.LogDebug($"Get:{url}");
|
_logger.LogDebug($"Get:{url}");
|
||||||
var result = await client.GetAsync(url);
|
var result = await client.GetAsync(url);
|
||||||
var strResult = await result.Content.ReadAsStringAsync();
|
var strResult = await result.Content.ReadAsStringAsync();
|
||||||
@@ -87,11 +99,11 @@ namespace Hua.DDNS.Common.Http
|
|||||||
#region 下载文件
|
#region 下载文件
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// http下载文件
|
/// 通过 HTTP 下载文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="url">下载文件地址</param>
|
/// <param name="url">下载文件地址</param>
|
||||||
/// <param name="localPath">文件存放地址,包含文件名</param>
|
/// <param name="localPath">文件本地存放路径,包含文件名</param>
|
||||||
/// <returns></returns>
|
/// <returns>下载成功返回 true,否则返回 false</returns>
|
||||||
public bool DownloadFile(string url, string localPath)
|
public bool DownloadFile(string url, string localPath)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -134,8 +146,9 @@ namespace Hua.DDNS.Common.Http
|
|||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获得当前机器的公网 Ip
|
/// 获取当前机器的公网 IPv4 地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <returns>IPv4 地址字符串</returns>
|
||||||
public async Task<string> GetCurrentPublicIpv4()
|
public async Task<string> GetCurrentPublicIpv4()
|
||||||
{
|
{
|
||||||
using var client = new HttpClient();
|
using var client = new HttpClient();
|
||||||
@@ -146,12 +159,49 @@ namespace Hua.DDNS.Common.Http
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Http 助手接口
|
||||||
|
/// </summary>
|
||||||
public interface IHttpHelper
|
public interface IHttpHelper
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取当前机器的公网 IPv4 地址
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>IPv4 地址字符串</returns>
|
||||||
public Task<string> GetCurrentPublicIpv4();
|
public Task<string> GetCurrentPublicIpv4();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步执行 Post 请求并解析 JSON 结果
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TIn">输入数据类型</typeparam>
|
||||||
|
/// <typeparam name="TOut">输出结果类型</typeparam>
|
||||||
|
/// <param name="url">请求地址</param>
|
||||||
|
/// <param name="input">输入数据</param>
|
||||||
|
/// <param name="timeOut">超时时间 (秒)</param>
|
||||||
|
/// <returns>解析后的结果对象</returns>
|
||||||
public Task<TOut?> PostAsync<TIn, TOut>(string url, TIn input, int timeOut = 10);
|
public Task<TOut?> PostAsync<TIn, TOut>(string url, TIn input, int timeOut = 10);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步执行 Get 请求并解析 JSON 结果
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TOut">输出结果类型</typeparam>
|
||||||
|
/// <param name="url">请求地址</param>
|
||||||
|
/// <param name="timeOut">超时时间 (秒)</param>
|
||||||
|
/// <returns>解析后的结果对象</returns>
|
||||||
public Task<TOut?> GetAsync<TOut>(string url, int timeOut = 10);
|
public Task<TOut?> GetAsync<TOut>(string url, int timeOut = 10);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过 HTTP 下载文件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url">下载文件地址</param>
|
||||||
|
/// <param name="fileFullName">文件本地存放路径,包含文件名</param>
|
||||||
|
/// <returns>下载成功返回 true,否则返回 false</returns>
|
||||||
public bool DownloadFile(string url, string fileFullName);
|
public bool DownloadFile(string url, string fileFullName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取 HttpClient 实例
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>HttpClient 实例</returns>
|
||||||
public HttpClient GetHttpClient();
|
public HttpClient GetHttpClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,29 @@
|
|||||||
namespace Hua.DDNS.Common.Http
|
namespace Hua.DDNS.Common.Http
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Http 请求返回结果包装类
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">数据类型</typeparam>
|
||||||
public class HttpResult<T>
|
public class HttpResult<T>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 返回的数据内容
|
||||||
|
/// </summary>
|
||||||
public virtual T Data { get; set; }
|
public virtual T Data { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据描述信息
|
||||||
|
/// </summary>
|
||||||
public string DataDescription { get; set; }
|
public string DataDescription { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 结果状态码 (例如 200 为成功)
|
||||||
|
/// </summary>
|
||||||
public int Result { get; set; }
|
public int Result { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 返回的消息提示
|
||||||
|
/// </summary>
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,23 @@
|
|||||||
using System.Data;
|
using System.Data;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
using Npgsql;
|
using Npgsql;
|
||||||
|
|
||||||
namespace Hua.DDNS.Common
|
namespace Hua.DDNS.Common
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库操作助手类 (基于 Npgsql 和 Dapper)
|
||||||
|
/// </summary>
|
||||||
public class SqlHelper
|
public class SqlHelper
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly string _connectionString;
|
private readonly string _connectionString;
|
||||||
private readonly ILogger<SqlHelper> _logger;
|
private readonly ILogger<SqlHelper> _logger;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="configuration">配置对象</param>
|
||||||
|
/// <param name="logger">日志对象</param>
|
||||||
public SqlHelper(IConfiguration configuration, ILogger<SqlHelper> logger)
|
public SqlHelper(IConfiguration configuration, ILogger<SqlHelper> logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@@ -19,10 +27,10 @@ namespace Hua.DDNS.Common
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询所有结果
|
/// 查询所有结果
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T">实体类型</typeparam>
|
||||||
/// <param name="strSql"></param>
|
/// <param name="strSql">SQL 语句</param>
|
||||||
/// <returns></returns>
|
/// <returns>结果列表</returns>
|
||||||
/// <exception cref="Exception"></exception>
|
/// <exception cref="Exception">数据库连接或查询异常</exception>
|
||||||
public List<T> GetList<T>(string strSql)
|
public List<T> GetList<T>(string strSql)
|
||||||
{
|
{
|
||||||
var list = new List<T>();
|
var list = new List<T>();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace Hua.DDNS.DDNSProviders.Ali
|
|||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// DDNSProvider for Ali
|
/// 阿里云 DDNS 解析提供者
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AliDdnsProvider : IDdnsProvider
|
public class AliDdnsProvider : IDdnsProvider
|
||||||
{
|
{
|
||||||
@@ -25,6 +25,12 @@ namespace Hua.DDNS.DDNSProviders.Ali
|
|||||||
private readonly DdnsOption _ddnsOption;
|
private readonly DdnsOption _ddnsOption;
|
||||||
private readonly IMapper _mapper;
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="aliCloudOption">阿里云配置</param>
|
||||||
|
/// <param name="mapper">对象映射器</param>
|
||||||
|
/// <param name="ddnsOption">DDNS 配置</param>
|
||||||
public AliDdnsProvider(IOptions<AliCloudOption> aliCloudOption, IMapper mapper,IOptions<DdnsOption> ddnsOption)
|
public AliDdnsProvider(IOptions<AliCloudOption> aliCloudOption, IMapper mapper,IOptions<DdnsOption> ddnsOption)
|
||||||
{
|
{
|
||||||
_aliCloudOption = aliCloudOption.Value;
|
_aliCloudOption = aliCloudOption.Value;
|
||||||
@@ -41,9 +47,9 @@ namespace Hua.DDNS.DDNSProviders.Ali
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取解析记录列表
|
/// 异步获取阿里云上的域名解析记录列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns>解析记录列表</returns>
|
||||||
public async Task<IEnumerable<DnsRecord>?> GetRecordListAsync()
|
public async Task<IEnumerable<DnsRecord>?> GetRecordListAsync()
|
||||||
{
|
{
|
||||||
var record = (await _client.DescribeDomainRecordsAsync(new DescribeDomainRecordsRequest()
|
var record = (await _client.DescribeDomainRecordsAsync(new DescribeDomainRecordsRequest()
|
||||||
@@ -54,6 +60,11 @@ namespace Hua.DDNS.DDNSProviders.Ali
|
|||||||
return _mapper.Map<IEnumerable<DnsRecord>>(record);
|
return _mapper.Map<IEnumerable<DnsRecord>>(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步在阿里云上创建新的域名解析记录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="record">解析记录信息</param>
|
||||||
|
/// <returns>创建后的解析记录信息</returns>
|
||||||
public async Task<DnsRecord> CreateDnsRecordAsync(DnsRecord record)
|
public async Task<DnsRecord> CreateDnsRecordAsync(DnsRecord record)
|
||||||
{
|
{
|
||||||
var rep = await _client.AddDomainRecordAsync(_mapper.Map<AddDomainRecordRequest>(record));
|
var rep = await _client.AddDomainRecordAsync(_mapper.Map<AddDomainRecordRequest>(record));
|
||||||
@@ -61,11 +72,11 @@ namespace Hua.DDNS.DDNSProviders.Ali
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 变更解析记录列表
|
/// 异步批量修改阿里云上的域名解析记录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="newIp"></param>
|
/// <param name="newIp">新的 IP 地址</param>
|
||||||
/// <param name="records"></param>
|
/// <param name="records">需要修改的解析记录列表</param>
|
||||||
/// <returns></returns>
|
/// <returns>修改后的解析记录列表</returns>
|
||||||
public async Task<IEnumerable<DnsRecord>> ModifyRecordListAsync(string newIp, IEnumerable<DnsRecord> records)
|
public async Task<IEnumerable<DnsRecord>> ModifyRecordListAsync(string newIp, IEnumerable<DnsRecord> records)
|
||||||
{
|
{
|
||||||
foreach (var aliDomainRecord in records)
|
foreach (var aliDomainRecord in records)
|
||||||
@@ -75,5 +86,14 @@ namespace Hua.DDNS.DDNSProviders.Ali
|
|||||||
|
|
||||||
return records;
|
return records;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步清理无效证书
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Task CleanInvalidCertificatesAsync()
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -9,22 +9,22 @@ using Hua.DDNS.DDNSProviders.Namesilo;
|
|||||||
namespace Hua.DDNS.DDNSProviders
|
namespace Hua.DDNS.DDNSProviders
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// domain configuration class
|
/// DDNS 配置选项类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DdnsOption
|
public class DdnsOption
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// platform from 1 Ali 2 Tencent 3
|
/// 云平台类型 (1: 阿里云, 2: 腾讯云, 3: Namesilo)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PlatformEnum Platform { get; set; }
|
public PlatformEnum Platform { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// domain
|
/// 根域名 (例如: example.com)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Domain { get; set; }
|
public string Domain { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// sub domain, eg. www,git
|
/// 需要更新的子域名列表 (例如: ["www", "api", "@"])
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string[] SubDomainArray { get; set; }
|
public string[] SubDomainArray { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ namespace Hua.DDNS.DDNSProviders.Dnspod
|
|||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// DdnsProvider for Dnspod
|
/// Dnspod (腾讯云) DDNS 解析提供者
|
||||||
/// <remarks></remarks>
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DnspodDdnsProvider : IDdnsProvider
|
public class DnspodDdnsProvider : IDdnsProvider
|
||||||
{
|
{
|
||||||
@@ -29,6 +28,12 @@ namespace Hua.DDNS.DDNSProviders.Dnspod
|
|||||||
private readonly DdnsOption _ddnsOption;
|
private readonly DdnsOption _ddnsOption;
|
||||||
private readonly IMapper _mapper;
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mapper">对象映射器</param>
|
||||||
|
/// <param name="tencentCloudOption">腾讯云配置</param>
|
||||||
|
/// <param name="ddnsOption">DDNS 配置</param>
|
||||||
public DnspodDdnsProvider(IMapper mapper, IOptions<TencentCloudOption> tencentCloudOption, IOptions<DdnsOption> ddnsOption)
|
public DnspodDdnsProvider(IMapper mapper, IOptions<TencentCloudOption> tencentCloudOption, IOptions<DdnsOption> ddnsOption)
|
||||||
{
|
{
|
||||||
_mapper = mapper;
|
_mapper = mapper;
|
||||||
@@ -44,6 +49,10 @@ namespace Hua.DDNS.DDNSProviders.Dnspod
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步获取 Dnspod 上的域名解析记录列表
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>解析记录列表</returns>
|
||||||
public async Task<IEnumerable<DnsRecord>?> GetRecordListAsync()
|
public async Task<IEnumerable<DnsRecord>?> GetRecordListAsync()
|
||||||
{
|
{
|
||||||
var recordList = (await _client.DescribeRecordList(new DescribeRecordListRequest() { Domain = _ddnsOption.Domain })).RecordList;
|
var recordList = (await _client.DescribeRecordList(new DescribeRecordListRequest() { Domain = _ddnsOption.Domain })).RecordList;
|
||||||
@@ -51,6 +60,11 @@ namespace Hua.DDNS.DDNSProviders.Dnspod
|
|||||||
return _mapper.Map<IEnumerable<DnsRecord>>(recordList);
|
return _mapper.Map<IEnumerable<DnsRecord>>(recordList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步在 Dnspod 上创建新的域名解析记录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="record">解析记录信息</param>
|
||||||
|
/// <returns>创建后的解析记录信息</returns>
|
||||||
public async Task<DnsRecord> CreateDnsRecordAsync(DnsRecord record)
|
public async Task<DnsRecord> CreateDnsRecordAsync(DnsRecord record)
|
||||||
{
|
{
|
||||||
var response = await _client.CreateRecord(new CreateRecordRequest()
|
var response = await _client.CreateRecord(new CreateRecordRequest()
|
||||||
@@ -64,6 +78,12 @@ namespace Hua.DDNS.DDNSProviders.Dnspod
|
|||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步批量修改 Dnspod 上的域名解析记录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newIp">新的 IP 地址</param>
|
||||||
|
/// <param name="records">需要修改的解析记录列表</param>
|
||||||
|
/// <returns>修改后的解析记录列表</returns>
|
||||||
public async Task<IEnumerable<DnsRecord>> ModifyRecordListAsync(string newIp, IEnumerable<DnsRecord> records)
|
public async Task<IEnumerable<DnsRecord>> ModifyRecordListAsync(string newIp, IEnumerable<DnsRecord> records)
|
||||||
{
|
{
|
||||||
var rep = await _client.ModifyRecordBatch(new ModifyRecordBatchRequest()
|
var rep = await _client.ModifyRecordBatch(new ModifyRecordBatchRequest()
|
||||||
@@ -74,5 +94,14 @@ namespace Hua.DDNS.DDNSProviders.Dnspod
|
|||||||
});
|
});
|
||||||
return records;
|
return records;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步清理无效证书
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Task CleanInvalidCertificatesAsync()
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
namespace Hua.DDNS.DDNSProviders.Dnspod
|
namespace Hua.DDNS.DDNSProviders.Dnspod
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// domain configuration Dnspod
|
/// Dnspod 配置选项
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DnspodOption
|
public class DnspodOption
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Endpoint dnspod.tencentcloudapi.com
|
/// 接口访问端点 (例如: dnspod.tencentcloudapi.com)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Endpoint { get; set; }
|
public string Endpoint { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,32 +9,37 @@ namespace Hua.DDNS.DDNSProviders
|
|||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Dynamic domain name resolution provider
|
/// 动态域名解析 (DDNS) 提供者接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IDdnsProvider
|
public interface IDdnsProvider
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取域名解析记录列表
|
/// 异步获取域名解析记录列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns>域名解析记录列表</returns>
|
||||||
|
|
||||||
Task<IEnumerable<DnsRecord>?> GetRecordListAsync();
|
Task<IEnumerable<DnsRecord>?> GetRecordListAsync();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建解析记录
|
/// 异步创建新的域名解析记录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="record"></param>
|
/// <param name="record">解析记录信息</param>
|
||||||
/// <returns></returns>
|
/// <returns>创建后的解析记录信息</returns>
|
||||||
Task<DnsRecord> CreateDnsRecordAsync(DnsRecord record);
|
Task<DnsRecord> CreateDnsRecordAsync(DnsRecord record);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 修改域名解析记录
|
/// 异步批量修改域名解析记录 (通常用于更新 IP)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="newIp"></param>
|
/// <param name="newIp">新的 IP 地址</param>
|
||||||
/// <param name="records"></param>
|
/// <param name="records">需要修改的解析记录列表</param>
|
||||||
/// <returns></returns>
|
/// <returns>修改后的解析记录列表</returns>
|
||||||
Task<IEnumerable<DnsRecord>> ModifyRecordListAsync(string newIp, IEnumerable<DnsRecord> records);
|
Task<IEnumerable<DnsRecord>> ModifyRecordListAsync(string newIp, IEnumerable<DnsRecord> records);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步清理无效证书
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task CleanInvalidCertificatesAsync();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Xml;
|
using System.Xml;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Hua.DDNS.Models;
|
using Hua.DDNS.Models;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
@@ -8,13 +8,18 @@ using Newtonsoft.Json;
|
|||||||
namespace Hua.DDNS.DDNSProviders.Namesilo
|
namespace Hua.DDNS.DDNSProviders.Namesilo
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// DDNSProvider for namesilo
|
/// Namesilo DDNS 解析提供者
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class NamesiloDdnsProvider : IDdnsProvider
|
public class NamesiloDdnsProvider : IDdnsProvider
|
||||||
{
|
{
|
||||||
public readonly NamesiloOption _namesiloOption;
|
public readonly NamesiloOption _namesiloOption;
|
||||||
public readonly DdnsOption _ddnsOption;
|
public readonly DdnsOption _ddnsOption;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="namesiloOption">Namesilo 配置</param>
|
||||||
|
/// <param name="ddnsOption">DDNS 配置</param>
|
||||||
public NamesiloDdnsProvider(IOptions<NamesiloOption> namesiloOption, IOptions<DdnsOption> ddnsOption)
|
public NamesiloDdnsProvider(IOptions<NamesiloOption> namesiloOption, IOptions<DdnsOption> ddnsOption)
|
||||||
{
|
{
|
||||||
_ddnsOption = ddnsOption.Value;
|
_ddnsOption = ddnsOption.Value;
|
||||||
@@ -22,6 +27,10 @@ namespace Hua.DDNS.DDNSProviders.Namesilo
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步获取 Namesilo 上的域名解析记录列表
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>解析记录列表</returns>
|
||||||
public async Task<IEnumerable<DnsRecord>?> GetRecordListAsync()
|
public async Task<IEnumerable<DnsRecord>?> GetRecordListAsync()
|
||||||
{
|
{
|
||||||
var client = new HttpClient();
|
var client = new HttpClient();
|
||||||
@@ -62,6 +71,11 @@ namespace Hua.DDNS.DDNSProviders.Namesilo
|
|||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步在 Namesilo 上创建新的域名解析记录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dnsRecord">解析记录信息</param>
|
||||||
|
/// <returns>创建后的解析记录信息</returns>
|
||||||
public async Task<DnsRecord> CreateDnsRecordAsync(DnsRecord dnsRecord)
|
public async Task<DnsRecord> CreateDnsRecordAsync(DnsRecord dnsRecord)
|
||||||
{
|
{
|
||||||
var host = dnsRecord.Host[..(dnsRecord.Host.Length - dnsRecord.Domain.Length - 1)];
|
var host = dnsRecord.Host[..(dnsRecord.Host.Length - dnsRecord.Domain.Length - 1)];
|
||||||
@@ -91,6 +105,12 @@ namespace Hua.DDNS.DDNSProviders.Namesilo
|
|||||||
return dnsRecord;
|
return dnsRecord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步批量修改 Namesilo 上的域名解析记录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newIp">新的 IP 地址</param>
|
||||||
|
/// <param name="records">需要修改的解析记录列表</param>
|
||||||
|
/// <returns>修改后的解析记录列表</returns>
|
||||||
public async Task<IEnumerable<DnsRecord>> ModifyRecordListAsync(string newIp, IEnumerable<DnsRecord> records)
|
public async Task<IEnumerable<DnsRecord>> ModifyRecordListAsync(string newIp, IEnumerable<DnsRecord> records)
|
||||||
{
|
{
|
||||||
foreach (var dnsRecord in records)
|
foreach (var dnsRecord in records)
|
||||||
@@ -122,5 +142,14 @@ namespace Hua.DDNS.DDNSProviders.Namesilo
|
|||||||
|
|
||||||
return records;
|
return records;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步清理无效证书
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Task CleanInvalidCertificatesAsync()
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
namespace Hua.DDNS.DDNSProviders.Namesilo
|
namespace Hua.DDNS.DDNSProviders.Namesilo
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Namesilo Option
|
/// Namesilo 配置选项
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class NamesiloOption
|
public class NamesiloOption
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// API key
|
/// API 密钥
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ApiKey { get; set; }
|
public string ApiKey { get; set; }
|
||||||
|
|
||||||
|
|||||||
+22
-2
@@ -25,6 +25,9 @@ using System.Net.Sockets;
|
|||||||
|
|
||||||
namespace Hua.DDNS.Jobs
|
namespace Hua.DDNS.Jobs
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 新的 DDNS 任务类,用于定期检查并更新域名解析记录
|
||||||
|
/// </summary>
|
||||||
[DisallowConcurrentExecution]
|
[DisallowConcurrentExecution]
|
||||||
public class NewJob : IJob, IDisposable
|
public class NewJob : IJob, IDisposable
|
||||||
{
|
{
|
||||||
@@ -32,10 +35,19 @@ namespace Hua.DDNS.Jobs
|
|||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly IServiceProvider _serviceProvider;
|
||||||
private readonly DdnsOption _ddnsOption;
|
private readonly DdnsOption _ddnsOption;
|
||||||
private readonly IHttpHelper _httpHelper;
|
private readonly IHttpHelper _httpHelper;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新的 IP 地址
|
||||||
|
/// </summary>
|
||||||
public string newIp;
|
public string newIp;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">日志对象</param>
|
||||||
|
/// <param name="httpHelper">Http 助手</param>
|
||||||
|
/// <param name="ddnsOption">DDNS 配置选项</param>
|
||||||
|
/// <param name="serviceProvider">服务提供者</param>
|
||||||
public NewJob(ILogger<NewJob> logger,IHttpHelper httpHelper,IOptions<DdnsOption> ddnsOption, IServiceProvider serviceProvider)
|
public NewJob(ILogger<NewJob> logger,IHttpHelper httpHelper,IOptions<DdnsOption> ddnsOption, IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@@ -43,6 +55,11 @@ namespace Hua.DDNS.Jobs
|
|||||||
_serviceProvider = serviceProvider;
|
_serviceProvider = serviceProvider;
|
||||||
_ddnsOption = ddnsOption.Value;
|
_ddnsOption = ddnsOption.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行任务逻辑
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context">作业执行上下文</param>
|
||||||
public async Task Execute(IJobExecutionContext context)
|
public async Task Execute(IJobExecutionContext context)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -98,6 +115,9 @@ namespace Hua.DDNS.Jobs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 释放资源
|
||||||
|
/// </summary>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_logger.LogInformation("AppJob已销毁");
|
_logger.LogInformation("AppJob已销毁");
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ using System.Security.Cryptography.X509Certificates;
|
|||||||
|
|
||||||
namespace Hua.DDNS.Jobs
|
namespace Hua.DDNS.Jobs
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// SSL 证书下载任务类,用于定期检查并更新 SSL 证书
|
||||||
|
/// </summary>
|
||||||
[DisallowConcurrentExecution]
|
[DisallowConcurrentExecution]
|
||||||
public class SslDownloadJob : IJob, IDisposable
|
public class SslDownloadJob : IJob, IDisposable
|
||||||
{
|
{
|
||||||
@@ -15,6 +18,12 @@ namespace Hua.DDNS.Jobs
|
|||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly IServiceProvider _serviceProvider;
|
||||||
private readonly SslDownloadOption _sslDownloadOption;
|
private readonly SslDownloadOption _sslDownloadOption;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">日志对象</param>
|
||||||
|
/// <param name="serviceProvider">服务提供者</param>
|
||||||
|
/// <param name="sslDownloadOption">SSL 下载配置选项</param>
|
||||||
public SslDownloadJob(
|
public SslDownloadJob(
|
||||||
ILogger<SslDownloadJob> logger,
|
ILogger<SslDownloadJob> logger,
|
||||||
IServiceProvider serviceProvider,
|
IServiceProvider serviceProvider,
|
||||||
@@ -25,6 +34,10 @@ namespace Hua.DDNS.Jobs
|
|||||||
_sslDownloadOption = sslDownloadOption.Value;
|
_sslDownloadOption = sslDownloadOption.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行任务逻辑
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context">作业执行上下文</param>
|
||||||
public async Task Execute(IJobExecutionContext context)
|
public async Task Execute(IJobExecutionContext context)
|
||||||
{
|
{
|
||||||
if (!_sslDownloadOption.Enabled)
|
if (!_sslDownloadOption.Enabled)
|
||||||
@@ -110,6 +123,11 @@ namespace Hua.DDNS.Jobs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取本地证书的过期时间
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">下载项</param>
|
||||||
|
/// <returns>过期时间,如果不存在则返回 null</returns>
|
||||||
private DateTime? GetLocalCertificateExpiry(SslDownloadItem item)
|
private DateTime? GetLocalCertificateExpiry(SslDownloadItem item)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -137,6 +155,14 @@ namespace Hua.DDNS.Jobs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步下载证书文件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="provider">SSL 提供者</param>
|
||||||
|
/// <param name="item">下载项</param>
|
||||||
|
/// <param name="certificateId">证书 ID</param>
|
||||||
|
/// <param name="domain">域名</param>
|
||||||
|
/// <returns>Task</returns>
|
||||||
private async Task DownloadFileAsync(ISslDownloadProvider provider, SslDownloadItem item, string certificateId, string domain)
|
private async Task DownloadFileAsync(ISslDownloadProvider provider, SslDownloadItem item, string certificateId, string domain)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -169,6 +195,9 @@ namespace Hua.DDNS.Jobs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 释放资源
|
||||||
|
/// </summary>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_logger.LogInformation("SslDownloadJob已销毁");
|
_logger.LogInformation("SslDownloadJob已销毁");
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -6,22 +6,60 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Hua.DDNS.Models;
|
namespace Hua.DDNS.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 域名解析记录实体类
|
||||||
|
/// </summary>
|
||||||
public class DnsRecord
|
public class DnsRecord
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 解析记录 ID
|
||||||
|
/// </summary>
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IP 地址
|
||||||
|
/// </summary>
|
||||||
public string Ip { get; set; }
|
public string Ip { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 主机记录 (例如: www)
|
||||||
|
/// </summary>
|
||||||
public string Host { get; set; }
|
public string Host { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 子域名 (通常与 Host 相同)
|
||||||
|
/// </summary>
|
||||||
public string SubDomain { get; set; }
|
public string SubDomain { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根域名 (例如: example.com)
|
||||||
|
/// </summary>
|
||||||
public string Domain { get; set; }
|
public string Domain { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生存时间 (TTL)
|
||||||
|
/// </summary>
|
||||||
public string TTL { get; set; } = "10";
|
public string TTL { get; set; } = "10";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 记录类型 (A, AAAA, CNAME 等)
|
||||||
|
/// </summary>
|
||||||
public string RecordType { get; set; } = "A";
|
public string RecordType { get; set; } = "A";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip">IP 地址</param>
|
||||||
|
/// <param name="domain">域名</param>
|
||||||
public DnsRecord(string ip,string domain)
|
public DnsRecord(string ip,string domain)
|
||||||
{
|
{
|
||||||
Ip = ip;
|
Ip = ip;
|
||||||
Host = domain;
|
Host = domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认构造函数
|
||||||
|
/// </summary>
|
||||||
public DnsRecord()
|
public DnsRecord()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -10,8 +10,14 @@ using TencentCloud.Dnspod.V20210323.Models;
|
|||||||
|
|
||||||
namespace Hua.DDNS.Models
|
namespace Hua.DDNS.Models
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// AutoMapper 对象映射配置类
|
||||||
|
/// </summary>
|
||||||
public class MappingProfile : Profile
|
public class MappingProfile : Profile
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数,配置映射规则
|
||||||
|
/// </summary>
|
||||||
public MappingProfile()
|
public MappingProfile()
|
||||||
{
|
{
|
||||||
CreateMap<DescribeDomainRecordsResponseBody.DescribeDomainRecordsResponseBodyDomainRecords.DescribeDomainRecordsResponseBodyDomainRecordsRecord, DnsRecord>()
|
CreateMap<DescribeDomainRecordsResponseBody.DescribeDomainRecordsResponseBodyDomainRecords.DescribeDomainRecordsResponseBodyDomainRecordsRecord, DnsRecord>()
|
||||||
|
|||||||
@@ -8,12 +8,20 @@ using Microsoft.Extensions.Options;
|
|||||||
|
|
||||||
namespace Hua.DDNS.SslProviders.Ali
|
namespace Hua.DDNS.SslProviders.Ali
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 阿里云 SSL 证书下载提供者
|
||||||
|
/// </summary>
|
||||||
public class AliSslProvider : ISslDownloadProvider
|
public class AliSslProvider : ISslDownloadProvider
|
||||||
{
|
{
|
||||||
private readonly Client _client;
|
private readonly Client _client;
|
||||||
private readonly AliCloudOption _aliCloudOption;
|
private readonly AliCloudOption _aliCloudOption;
|
||||||
private readonly ILogger<AliSslProvider> _logger;
|
private readonly ILogger<AliSslProvider> _logger;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">日志对象</param>
|
||||||
|
/// <param name="aliCloudOption">阿里云配置</param>
|
||||||
public AliSslProvider(
|
public AliSslProvider(
|
||||||
ILogger<AliSslProvider> logger,
|
ILogger<AliSslProvider> logger,
|
||||||
IOptions<AliCloudOption> aliCloudOption)
|
IOptions<AliCloudOption> aliCloudOption)
|
||||||
@@ -31,12 +39,40 @@ namespace Hua.DDNS.SslProviders.Ali
|
|||||||
_client = new Client(config);
|
_client = new Client(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步获取阿里云上的 SSL 证书列表
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>证书列表</returns>
|
||||||
public async Task<List<SslCertificate>> GetCertificatesAsync()
|
public async Task<List<SslCertificate>> GetCertificatesAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.LogWarning("阿里云 SSL 证书列表功能待实现");
|
var request = new ListUserCertificateOrderRequest
|
||||||
return new List<SslCertificate>();
|
{
|
||||||
|
OrderType = "CERT",
|
||||||
|
Status = "ISSUED" // 也可以不设置,获取所有
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await _client.ListUserCertificateOrderAsync(request);
|
||||||
|
var certificates = new List<SslCertificate>();
|
||||||
|
|
||||||
|
if (response.Body.CertificateOrderList != null)
|
||||||
|
{
|
||||||
|
foreach (var cert in response.Body.CertificateOrderList)
|
||||||
|
{
|
||||||
|
certificates.Add(new SslCertificate
|
||||||
|
{
|
||||||
|
CertificateId = cert.CertificateId.ToString(),
|
||||||
|
Domain = cert.Domain,
|
||||||
|
Alias = cert.Name,
|
||||||
|
CertEndTime = string.IsNullOrEmpty(cert.EndDate) ? DateTime.MinValue : DateTime.Parse(cert.EndDate),
|
||||||
|
StatusMsg = cert.Status
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation($"获取到 {certificates.Count} 个阿里云 SSL 证书");
|
||||||
|
return certificates;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -45,10 +81,18 @@ namespace Hua.DDNS.SslProviders.Ali
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步下载阿里云上的指定的 SSL 证书
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="certificateId">证书 ID</param>
|
||||||
|
/// <param name="savePath">本地保存目录路径</param>
|
||||||
|
/// <param name="fileName">保存的文件名 (不含后缀)</param>
|
||||||
|
/// <returns>下载成功返回 true,否则返回 false</returns>
|
||||||
public async Task<bool> DownloadCertificateAsync(string certificateId, string savePath, string fileName)
|
public async Task<bool> DownloadCertificateAsync(string certificateId, string savePath, string fileName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// TODO: 阿里云证书下载逻辑
|
||||||
_logger.LogWarning($"阿里云 SSL 证书下载功能待实现: {certificateId}");
|
_logger.LogWarning($"阿里云 SSL 证书下载功能待实现: {certificateId}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -58,5 +102,41 @@ namespace Hua.DDNS.SslProviders.Ali
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步清理无效证书
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task CleanInvalidCertificatesAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var certificates = await GetCertificatesAsync();
|
||||||
|
// 筛选过期的证书
|
||||||
|
var expiredCertificates = certificates.Where(c => c.CertEndTime != DateTime.MinValue && c.CertEndTime < DateTime.Now).ToList();
|
||||||
|
|
||||||
|
foreach (var cert in expiredCertificates)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var deleteRequest = new DeleteUserCertificateRequest
|
||||||
|
{
|
||||||
|
CertId = long.Parse(cert.CertificateId)
|
||||||
|
};
|
||||||
|
await _client.DeleteUserCertificateAsync(deleteRequest);
|
||||||
|
_logger.LogInformation($"已删除阿里云过期证书: {cert.Domain} ({cert.CertificateId}), 过期时间: {cert.CertEndTime}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, $"删除阿里云证书失败: {cert.CertificateId}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "清理阿里云无效证书失败");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,70 @@
|
|||||||
namespace Hua.DDNS.SslProviders
|
namespace Hua.DDNS.SslProviders
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// SSL 证书下载提供者接口
|
||||||
|
/// </summary>
|
||||||
public interface ISslDownloadProvider
|
public interface ISslDownloadProvider
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 异步获取 SSL 证书列表
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>证书信息列表</returns>
|
||||||
Task<List<SslCertificate>> GetCertificatesAsync();
|
Task<List<SslCertificate>> GetCertificatesAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步下载指定的 SSL 证书
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="certificateId">证书 ID</param>
|
||||||
|
/// <param name="savePath">本地保存目录路径</param>
|
||||||
|
/// <param name="fileName">保存的文件名 (不含后缀)</param>
|
||||||
|
/// <returns>下载成功返回 true,否则返回 false</returns>
|
||||||
Task<bool> DownloadCertificateAsync(string certificateId, string savePath, string fileName);
|
Task<bool> DownloadCertificateAsync(string certificateId, string savePath, string fileName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步清理无效证书
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task CleanInvalidCertificatesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SSL 证书信息类
|
||||||
|
/// </summary>
|
||||||
public class SslCertificate
|
public class SslCertificate
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 证书 ID
|
||||||
|
/// </summary>
|
||||||
public string CertificateId { get; set; }
|
public string CertificateId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 证书关联的域名
|
||||||
|
/// </summary>
|
||||||
public string Domain { get; set; }
|
public string Domain { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 证书别名
|
||||||
|
/// </summary>
|
||||||
public string Alias { get; set; }
|
public string Alias { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 证书生效时间
|
||||||
|
/// </summary>
|
||||||
public DateTime CertBeginTime { get; set; }
|
public DateTime CertBeginTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 证书过期时间
|
||||||
|
/// </summary>
|
||||||
public DateTime CertEndTime { get; set; }
|
public DateTime CertEndTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 状态码
|
||||||
|
/// </summary>
|
||||||
public int Status { get; set; }
|
public int Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 状态消息
|
||||||
|
/// </summary>
|
||||||
public string StatusMsg { get; set; }
|
public string StatusMsg { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,20 @@ using System.IO.Compression;
|
|||||||
|
|
||||||
namespace Hua.DDNS.SslProviders.Tencent
|
namespace Hua.DDNS.SslProviders.Tencent
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 腾讯云 SSL 证书下载提供者
|
||||||
|
/// </summary>
|
||||||
public class TencentSslProvider : ISslDownloadProvider
|
public class TencentSslProvider : ISslDownloadProvider
|
||||||
{
|
{
|
||||||
private readonly SslClient _client;
|
private readonly SslClient _client;
|
||||||
private readonly TencentCloudOption _tencentCloudOption;
|
private readonly TencentCloudOption _tencentCloudOption;
|
||||||
private readonly ILogger<TencentSslProvider> _logger;
|
private readonly ILogger<TencentSslProvider> _logger;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">日志对象</param>
|
||||||
|
/// <param name="tencentCloudOption">腾讯云配置</param>
|
||||||
public TencentSslProvider(
|
public TencentSslProvider(
|
||||||
ILogger<TencentSslProvider> logger,
|
ILogger<TencentSslProvider> logger,
|
||||||
IOptions<TencentCloudOption> tencentCloudOption)
|
IOptions<TencentCloudOption> tencentCloudOption)
|
||||||
@@ -32,6 +40,10 @@ namespace Hua.DDNS.SslProviders.Tencent
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步获取腾讯云上的 SSL 证书列表
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>证书信息列表</returns>
|
||||||
public async Task<List<SslCertificate>> GetCertificatesAsync()
|
public async Task<List<SslCertificate>> GetCertificatesAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -72,6 +84,13 @@ namespace Hua.DDNS.SslProviders.Tencent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步下载腾讯云上的指定的 SSL 证书
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="certificateId">证书 ID</param>
|
||||||
|
/// <param name="savePath">本地保存目录路径</param>
|
||||||
|
/// <param name="fileName">保存的文件名 (不含后缀)</param>
|
||||||
|
/// <returns>下载成功返回 true,否则返回 false</returns>
|
||||||
public async Task<bool> DownloadCertificateAsync(string certificateId, string savePath, string fileName)
|
public async Task<bool> DownloadCertificateAsync(string certificateId, string savePath, string fileName)
|
||||||
{
|
{
|
||||||
string tempZipPath = null;
|
string tempZipPath = null;
|
||||||
@@ -172,5 +191,41 @@ namespace Hua.DDNS.SslProviders.Tencent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步清理无效证书
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task CleanInvalidCertificatesAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var certificates = await GetCertificatesAsync();
|
||||||
|
// 清理已过期的证书 (Status 为 10 或者当前时间已过过期时间)
|
||||||
|
var expiredCertificates = certificates.Where(c => c.CertEndTime < DateTime.Now || c.Status == 10).ToList();
|
||||||
|
|
||||||
|
foreach (var cert in expiredCertificates)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var deleteRequest = new DeleteCertificateRequest
|
||||||
|
{
|
||||||
|
CertificateId = cert.CertificateId
|
||||||
|
};
|
||||||
|
await _client.DeleteCertificate(deleteRequest);
|
||||||
|
_logger.LogInformation($"已删除腾讯云过期证书: {cert.Domain} ({cert.CertificateId}), 过期时间: {cert.CertEndTime}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, $"删除腾讯云证书失败: {cert.CertificateId}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "清理腾讯云无效证书失败");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-17
@@ -18,10 +18,18 @@ using Serilog.Extensions.Logging;
|
|||||||
|
|
||||||
namespace Hua.DDNS.Start
|
namespace Hua.DDNS.Start
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 应用程序入口类
|
||||||
|
/// </summary>
|
||||||
public static class Program
|
public static class Program
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 主入口方法
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">命令行参数</param>
|
||||||
public static async Task Main(string[] args)
|
public static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
|
// 配置 Serilog 日志
|
||||||
Log.Logger = new LoggerConfiguration()
|
Log.Logger = new LoggerConfiguration()
|
||||||
.Enrich.FromLogContext()
|
.Enrich.FromLogContext()
|
||||||
.WriteTo.Console()
|
.WriteTo.Console()
|
||||||
@@ -33,13 +41,18 @@ namespace Hua.DDNS.Start
|
|||||||
await CreateHostBuilder(args).Build().RunAsync();
|
await CreateHostBuilder(args).Build().RunAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建并配置宿主构造器
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">命令行参数</param>
|
||||||
|
/// <returns>IHostBuilder 实例</returns>
|
||||||
private static IHostBuilder CreateHostBuilder(string[] args) =>
|
private static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||||
Host.CreateDefaultBuilder(args)
|
Host.CreateDefaultBuilder(args)
|
||||||
.UseWindowsService()
|
.UseWindowsService() // 支持作为 Windows 服务运行
|
||||||
.UseSerilog()
|
.UseSerilog() // 使用 Serilog 替代默认日志
|
||||||
.ConfigureAppConfiguration((context, config) =>
|
.ConfigureAppConfiguration((context, config) =>
|
||||||
{
|
{
|
||||||
// clear all config provider
|
// 清理并重新配置配置源
|
||||||
config.Sources.Clear();
|
config.Sources.Clear();
|
||||||
config
|
config
|
||||||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
@@ -49,15 +62,25 @@ namespace Hua.DDNS.Start
|
|||||||
.ConfigureServices((hostContext, services) =>
|
.ConfigureServices((hostContext, services) =>
|
||||||
{
|
{
|
||||||
services.AddAutoMapper(Assembly.GetExecutingAssembly());
|
services.AddAutoMapper(Assembly.GetExecutingAssembly());
|
||||||
|
|
||||||
|
// 绑定配置选项
|
||||||
services.Configure<DdnsOption>(hostContext.Configuration.GetSection("DDNS"));
|
services.Configure<DdnsOption>(hostContext.Configuration.GetSection("DDNS"));
|
||||||
services.Configure<NamesiloOption>(hostContext.Configuration.GetSection("Namesilo"));
|
services.Configure<NamesiloOption>(hostContext.Configuration.GetSection("Namesilo"));
|
||||||
services.Configure<TencentCloudOption>(hostContext.Configuration.GetSection("TencentCloud"));
|
services.Configure<TencentCloudOption>(hostContext.Configuration.GetSection("TencentCloud"));
|
||||||
services.Configure<AliCloudOption>(hostContext.Configuration.GetSection("AliCloud"));
|
services.Configure<AliCloudOption>(hostContext.Configuration.GetSection("AliCloud"));
|
||||||
services.Configure<SslDownloadOption>(hostContext.Configuration.GetSection("SslDownload"));
|
services.Configure<SslDownloadOption>(hostContext.Configuration.GetSection("SslDownload"));
|
||||||
|
|
||||||
|
// 配置依赖注入和 Quartz
|
||||||
ConfigDi(hostContext, services);
|
ConfigDi(hostContext, services);
|
||||||
ConfigQuartz(hostContext, services);
|
ConfigQuartz(hostContext, services);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置依赖注入 (DI)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hostContext">宿主上下文</param>
|
||||||
|
/// <param name="services">服务集合</param>
|
||||||
|
/// <returns>IServiceProvider 实例</returns>
|
||||||
public static IServiceProvider ConfigDi(HostBuilderContext hostContext, IServiceCollection services)
|
public static IServiceProvider ConfigDi(HostBuilderContext hostContext, IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddSingleton<SettingProvider>();
|
services.AddSingleton<SettingProvider>();
|
||||||
@@ -72,29 +95,31 @@ namespace Hua.DDNS.Start
|
|||||||
return services.BuildServiceProvider();
|
return services.BuildServiceProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置 Quartz 定时任务
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hostContext">宿主上下文</param>
|
||||||
|
/// <param name="services">服务集合</param>
|
||||||
private static void ConfigQuartz(HostBuilderContext hostContext, IServiceCollection services)
|
private static void ConfigQuartz(HostBuilderContext hostContext, IServiceCollection services)
|
||||||
{
|
{
|
||||||
// if you are using persistent job store, you might want to alter some options
|
// 配置 Quartz 选项
|
||||||
services.Configure<QuartzOptions>(options =>
|
services.Configure<QuartzOptions>(options =>
|
||||||
{
|
{
|
||||||
options.Scheduling.IgnoreDuplicates = true; // default: false
|
options.Scheduling.IgnoreDuplicates = true; // 忽略重复任务
|
||||||
options.Scheduling.OverWriteExistingData = true; // default: true
|
options.Scheduling.OverWriteExistingData = true; // 覆盖现有数据
|
||||||
});
|
});
|
||||||
|
|
||||||
// base configuration for DI
|
// 添加 Quartz 服务
|
||||||
services.AddQuartz(q =>
|
services.AddQuartz(q =>
|
||||||
{
|
{
|
||||||
// handy when part of cluster or you want to otherwise identify ltiple schedulers
|
|
||||||
q.SchedulerId = "Hua.DDNS.Demo";
|
q.SchedulerId = "Hua.DDNS.Demo";
|
||||||
// this is default configuration if you don't alter it
|
|
||||||
q.UseMicrosoftDependencyInjectionJobFactory();
|
q.UseMicrosoftDependencyInjectionJobFactory();
|
||||||
|
|
||||||
// these are the defaults
|
|
||||||
q.UseSimpleTypeLoader();
|
q.UseSimpleTypeLoader();
|
||||||
q.UseInMemoryStore();
|
q.UseInMemoryStore();
|
||||||
q.UseDefaultThreadPool(tp => { tp.MaxConcurrency = 10; });
|
q.UseDefaultThreadPool(tp => { tp.MaxConcurrency = 10; });
|
||||||
|
|
||||||
//configure jobs with code
|
// 配置 DDNS 任务 (NewJob)
|
||||||
var appJobKey = new JobKey("NewJob", "NewJobGroup");
|
var appJobKey = new JobKey("NewJob", "NewJobGroup");
|
||||||
q.AddJob<NewJob>(j => j
|
q.AddJob<NewJob>(j => j
|
||||||
.StoreDurably()
|
.StoreDurably()
|
||||||
@@ -110,6 +135,7 @@ namespace Hua.DDNS.Start
|
|||||||
.StartNow()
|
.StartNow()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 配置 SSL 下载任务 (SslDownloadJob)
|
||||||
var sslDownloadJobKey = new JobKey("SslDownloadJob", "SslDownloadJobGroup");
|
var sslDownloadJobKey = new JobKey("SslDownloadJob", "SslDownloadJobGroup");
|
||||||
q.AddJob<SslDownloadJob>(j => j
|
q.AddJob<SslDownloadJob>(j => j
|
||||||
.StoreDurably()
|
.StoreDurably()
|
||||||
@@ -132,14 +158,11 @@ namespace Hua.DDNS.Start
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Quartz.Extensions.Hosting hosting
|
// 添加 Quartz 托管服务
|
||||||
services.AddQuartzHostedService(options =>
|
services.AddQuartzHostedService(options =>
|
||||||
{
|
{
|
||||||
// when shutting down we want jobs to complete gracefully
|
options.WaitForJobsToComplete = true; // 优雅退出
|
||||||
options.WaitForJobsToComplete = true;
|
options.StartDelay = TimeSpan.FromSeconds(10); // 启动延迟
|
||||||
|
|
||||||
// when we need to init another IHostedServices first
|
|
||||||
options.StartDelay = TimeSpan.FromSeconds(10);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user