Serilog实战:如何在ASP.NET Core项目中配置结构化日志(含Elasticsearch集成)
Serilog实战如何在ASP.NET Core项目中配置结构化日志含Elasticsearch集成在构建现代Web应用时日志系统的重要性常常被低估直到某个深夜你被一个线上问题惊醒却发现自己面对着一堆难以解读的、杂乱无章的日志文本。对于ASP.NET Core开发者而言一个设计良好的日志系统不仅是调试的利器更是洞察应用行为、监控系统健康、甚至进行业务分析的宝贵数据源。传统的字符串拼接式日志就像一本没有目录和索引的日记查找和分析效率低下。而结构化日志则为我们提供了一种将日志数据“数据库化”的可能让每一次记录都成为结构化的、可查询的事件。Serilog正是.NET生态中实现这一目标的佼佼者。它不仅仅是一个日志库更是一套完整的结构化日志记录框架。与ASP.NET Core原生日志系统无缝集成后Serilog能将HTTP请求、业务操作、异常堆栈等所有信息转化为富含上下文的结构化数据。无论是输出到控制台进行本地调试还是写入文件进行持久化亦或是实时发送到Elasticsearch这样的分布式搜索引擎中构建强大的日志分析平台Serilog都能提供优雅而强大的支持。本文旨在为需要将专业级日志系统集成到Web应用中的开发者提供一份从基础配置到高级集成的实战指南。我们将绕过泛泛而谈的概念直接切入实际开发中的配置细节、最佳实践以及那些容易踩坑的常见问题解决方案。无论你是希望替换掉项目中原生简陋的日志输出还是计划构建一个面向生产环境的、集中式的日志监控体系这里的内容都将为你提供清晰的路径和可靠的代码示例。1. 从零开始在ASP.NET Core中集成Serilog在引入任何第三方库之前理解其与现有框架的融合方式是关键。ASP.NET Core自带了一套基于ILogger接口的日志抽象这为我们替换底层实现提供了极大的便利。Serilog通过Serilog.AspNetCore这个包能够完美地“嵌入”到这个抽象层之下接管所有的日志记录工作。1.1 项目初始化与包引用首先创建一个新的ASP.NET Core Web API项目或者在你现有的项目中开始操作。通过NuGet包管理器或命令行工具添加必要的Serilog包。这里我们不仅需要核心库和基础输出目标Sink还需要专门用于ASP.NET Core集成的包。dotnet add package Serilog.AspNetCore dotnet add package Serilog.Sinks.Console dotnet add package Serilog.Sinks.File注意Serilog.AspNetCore包是一个元包它已经包含了Serilog、Serilog.Extensions.Logging以及一些常用的Enricher日志属性增强器。单独安装它通常就足够了但为了明确依赖和版本控制你也可以选择单独安装上述各个包。安装完成后传统的做法是在Program.cs的入口处直接配置Log.Logger这个全局静态记录器。然而在ASP.NET Core的现代最小托管模型下我们有更优雅的、与宿主构建器深度集成的方式。1.2 最小托管模型下的配置让我们看看如何在Program.cs中以最简洁的方式完成Serilog的初始化和集成。using Serilog; var builder WebApplication.CreateBuilder(args); // 关键步骤在构建Host之前配置并启用Serilog builder.Host.UseSerilog((hostingContext, loggerConfiguration) { loggerConfiguration .ReadFrom.Configuration(hostingContext.Configuration) // 从appsettings.json读取配置 .Enrich.FromLogContext() // 允许动态添加上下文信息 .WriteTo.Console( outputTemplate: [{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}) .WriteTo.File(logs/app-.txt, rollingInterval: RollingInterval.Day, retainedFileCountLimit: 7); }); // 添加服务到容器 builder.Services.AddControllers(); var app builder.Build(); // 启用HTTP请求日志记录中间件强烈推荐 app.UseSerilogRequestLogging(); app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();这段代码做了几件重要的事情builder.Host.UseSerilog(...)这是集成Serilog的核心方法。它告诉ASP.NET Core使用Serilog作为其日志提供程序替换默认的实现。传入的配置委托可以访问宿主上下文和配置。ReadFrom.Configuration这是最佳实践。它将Serilog的配置外部化到appsettings.json文件中使得不同环境开发、生产可以有不同的日志配置而无需重新编译代码。Enrich.FromLogContext()启用日志上下文。这是一个非常强大的功能允许你在代码的任何地方为当前执行逻辑范围内的所有日志动态添加公共属性如TransactionId,UserId。UseSerilogRequestLogging()添加一个中间件自动为每个HTTP请求记录摘要日志包括请求路径、方法、状态码和耗时。这极大地简化了Web API的访问日志记录。1.3 理解并配置appsettings.json将配置转移到appsettings.json是管理复杂日志配置的推荐方式。下面是一个详细的配置示例{ Serilog: { Using: [ Serilog.Sinks.Console, Serilog.Sinks.File ], MinimumLevel: { Default: Information, Override: { Microsoft: Warning, System: Warning, MyApp.VerboseService: Debug } }, WriteTo: [ { Name: Console, Args: { outputTemplate: [{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext} {Message:lj}{NewLine}{Exception} } }, { Name: File, Args: { path: logs/log-.json, rollingInterval: Day, formatter: Serilog.Formatting.Json.JsonFormatter, Serilog } } ], Enrich: [ FromLogContext, WithMachineName, WithThreadId ], Properties: { Application: MyAspNetCoreApp, Environment: Development } } }这个配置定义了两个输出目标Sink一个格式化的控制台输出和一个JSON格式的文件输出。其中几个关键点层级日志级别默认记录Information及以上级别。但通过Override可以将Microsoft和System命名空间下的日志通常是框架自身的冗杂信息限制为Warning级别从而让控制台更清爽。同时可以为你自己的某个详细服务单独开启Debug级别。结构化JSON输出文件Sink使用了JsonFormatter。这意味着写入文件的每一行都是一个完整的JSON对象这是实现结构化日志分析和后续集成Elasticsearch的基础。属性增强通过Enrich添加了机器名和线程ID。通过Properties添加了固定的应用名称和环境属性。这些属性会附加到每一条日志上。2. 掌握核心结构化日志的威力与实践结构化日志是Serilog的灵魂。它摒弃了传统的字符串插值或拼接转而采用命名占位符的方式记录日志。这不仅仅是语法上的改变更是思维方式的升级——日志从“文本”变成了“事件数据”。2.1 从文本日志到事件数据假设我们有一个用户登录的场景。传统的方式可能是这样的_logger.LogInformation($User {userId} from {ipAddress} logged in at {loginTime}.);这种方式有几个问题1) 难以解析如果想找出所有来自特定IP的登录需要写复杂的正则表达式。2) 参数userId、ipAddress在日志文本中丢失了其语义变成了纯文本的一部分。使用Serilog的结构化日志我们这样写_logger.LogInformation(User {UserId} from {IpAddress} logged in at {LoginTime}., userId, ipAddress, loginTime);注意占位符{UserId}是有名字的当使用支持结构化的格式如JSON输出时日志会变成这样{ Timestamp: 2023-10-27T10:30:00.123456Z, Level: Information, MessageTemplate: User {UserId} from {IpAddress} logged in at {LoginTime}., Properties: { UserId: 12345, IpAddress: 192.168.1.100, LoginTime: 2023-10-27T10:30:00.123456Z, SourceContext: MyApp.Services.AuthService, ... // 其他Enrich添加的属性 } }现在UserId、IpAddress都成为了日志事件对象中独立的、可查询的字段。你可以轻松地在Elasticsearch或Seq中执行类似Properties.IpAddress: 192.168.1.100的查询。2.2 利用LogContext添加上下文在Web请求或一个复杂业务流程中我们常常希望为一系列相关的日志自动添加相同的上下文信息比如当前请求的跟踪IDTraceId或操作的用户ID。手动为每个日志语句添加这些参数是繁琐且易错的。Serilog的LogContext来解决这个问题。你可以在一个逻辑作用域内“推送”属性该作用域内的所有日志都会自动包含这些属性。using Serilog.Context; public class OrderService { private readonly ILoggerOrderService _logger; public async Task ProcessOrderAsync(int orderId, int userId) { // 为当前异步控制流中的所有日志添加OrderId和UserId上下文 using (LogContext.PushProperty(OrderId, orderId)) using (LogContext.PushProperty(UserId, userId)) { _logger.LogInformation(Starting to process order.); // ... 复杂的业务逻辑 _logger.LogInformation(Order processing completed.); } } }这样在using作用域内产生的所有日志其JSON输出中都会自动包含OrderId: 1001和UserId: 123这两个属性无论这些日志是写在OrderService里还是它调用的其他服务里。这对于追踪一个请求的完整生命周期至关重要。2.3 性能考量与最佳实践结构化日志虽然强大但也需注意性能。不当的使用可能导致不必要的字符串分配和计算。避免在日志消息中直接进行复杂计算或调用方法// 不佳无论日志级别是否启用ToString()和复杂计算都会执行 _logger.LogDebug(Processed item: {Item}, expensiveObject.ToString()); // 更佳使用条件判断 if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug(Processed item: {Item}, expensiveObject.ToString()); }对于LogDebug、LogTrace等低级别日志在频繁执行的代码路径中先判断级别是否启用是一个好习惯。利用Serilog的延迟计算Serilog的某些接收器如Seq支持捕获复杂的对象结构但默认的文本格式化器还是会调用ToString()。对于复杂对象可以考虑自定义IDestructuringPolicy来优化序列化方式。3. 深入生产配置与输出到Elasticsearch将日志集中存储和索引是生产环境的标准做法。Elasticsearch以其强大的全文搜索和聚合分析能力成为日志管理ELK Stack中的E的首选。Serilog通过Serilog.Sinks.Elasticsearch包提供了开箱即用的支持。3.1 基础集成配置首先添加必要的NuGet包dotnet add package Serilog.Sinks.Elasticsearch接下来在appsettings.json中或代码中配置Elasticsearch Sink。以下是一个结合JSON配置和代码增强的示例。我们在appsettings.Production.json中配置生产环境的Elasticsearch地址{ Serilog: { WriteTo: [ { Name: Elasticsearch, Args: { nodeUris: http://elasticsearch-production:9200, indexFormat: myapp-logs-{0:yyyy.MM}, autoRegisterTemplate: true, numberOfShards: 1, numberOfReplicas: 1, bufferBaseFilename: ./logs/elasticsearch-buffer, failureCallback: e Console.WriteLine($Unable to submit event to Elasticsearch: {e.Message}) } } ] } }对应的在Program.cs中我们可以根据环境进行更精细的控制builder.Host.UseSerilog((hostingContext, loggerConfiguration) { loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration); // 如果是生产环境额外配置Elasticsearch Sink的一些细节 if (hostingContext.HostingEnvironment.IsProduction()) { var elasticsearchUri hostingContext.Configuration[Elasticsearch:Uri]; if (!string.IsNullOrEmpty(elasticsearchUri)) { loggerConfiguration.WriteTo.Elasticsearch( new ElasticsearchSinkOptions(new Uri(elasticsearchUri)) { AutoRegisterTemplate true, AutoRegisterTemplateVersion AutoRegisterTemplateVersion.ESv7, IndexFormat ${hostingContext.HostingEnvironment.ApplicationName?.ToLower().Replace(., -)}-logs-{{0:yyyy.MM}}, BatchAction ElasticOpType.Create, BufferBaseFilename ./logs/elasticsearch-buffer, FailureCallback e Console.WriteLine($Elasticsearch sink error: {e.Message}), EmitEventFailure EmitEventFailureHandling.WriteToSelfLog | EmitEventFailureHandling.WriteToFailureSink | EmitEventFailureHandling.RaiseCallback }); } } });关键配置项解析配置项说明建议值/说明AutoRegisterTemplate是否自动在ES中创建索引模板true。模板定义了日志字段的映射如UserId为integer类型确保字段类型一致便于聚合。IndexFormat索引名称格式myapp-logs-{0:yyyy.MM}。按月份滚动创建索引如myapp-logs-2023.10便于管理和按时间范围清理旧数据。BufferBaseFilename缓冲文件路径指定一个本地目录。当ES不可用时日志会先写入本地缓冲文件待ES恢复后重发防止日志丢失。这是生产环境必备选项。FailureCallback失败回调用于记录发送失败的事件方便监控集成健康状况。NumberOfShards/Replicas分片和副本数在索引模板中指定。根据日志量和集群规模调整。3.2 处理异常与复杂对象在将日志发送到Elasticsearch时确保异常信息和复杂对象能被正确序列化非常重要。Serilog默认能很好地处理异常。对于复杂对象Elasticsearch Sink会尝试将其序列化为JSON对象。try { // ... 可能抛出异常的操作 var complexOrder await _orderRepository.GetOrderWithDetailsAsync(orderId); _logger.LogInformation(Retrieved order {Order} for processing., complexOrder); } catch (Exception ex) { // 直接记录异常对象Serilog会展开其Message, StackTrace, InnerException等属性 _logger.LogError(ex, Failed to process order {OrderId}., orderId); }使用操作符如{Order}指示Serilog对对象进行“析构”destructure即将其属性展开为日志事件的顶级属性。这对于将复杂业务对象作为日志的一部分进行分析非常有用。但要注意避免记录包含敏感信息如密码、密钥或循环引用的过大对象。3.3 在Kibana中可视化日志日志进入Elasticsearch后你可以使用Kibana进行搜索和可视化。创建索引模式在Kibana的“Stack Management”中创建与你的IndexFormat匹配的索引模式例如myapp-logs-*。探索数据在“Discover”页面你可以看到所有日志。利用结构化日志的优势你可以在搜索栏使用KQLKibana Query Language进行精准查询例如level: Error查找所有错误。Properties.UserId: 12345查找该用户的所有操作。message: login AND Properties.IpAddress: 192.168.1.*组合查询。创建仪表盘你可以基于日志字段创建可视化图表例如按小时统计错误数量的折线图、按服务名称统计日志量的饼图、最近高频出现的错误信息列表等。4. 高级主题与运维实践一个健壮的日志系统不仅在于记录还在于管理和维护。以下是一些进阶主题和运维建议。4.1 动态日志级别控制在生产环境中有时为了调试一个棘手的问题需要临时将某个服务的日志级别从Information调整为Debug而不想重启应用。Serilog结合Serilog.Settings.Configuration可以实现这一点。你可以将日志级别配置放在可热重载的配置源中比如appsettings.json并使用IConfiguration的ReloadOnChange功能。当你在运行时修改配置文件并保存时Serilog的日志级别会随之更新。更高级的方案是集成像Serilog.Sinks.Map这样的包或者编写自定义的ILogEventFilter来实现基于特定条件如一个特定的HTTP Header或一个管理端点的动态过滤。4.2 自定义Enricher与过滤器除了内置的Enricher你可以创建自定义的Enricher来为所有日志添加业务相关的属性。public class ApplicationVersionEnricher : ILogEventEnricher { private readonly string _version; public ApplicationVersionEnricher() { _version Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? unknown; } public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) { var versionProperty propertyFactory.CreateProperty(ApplicationVersion, _version); logEvent.AddPropertyIfAbsent(versionProperty); } }在配置中启用它.Enrich.WithApplicationVersionEnricher()。同样你可以创建自定义过滤器例如过滤掉包含特定敏感关键词的日志或者在日志量过大时进行采样。4.3 性能监控与日志量控制无限制的日志记录会拖慢应用并迅速填满磁盘。以下是一些控制策略设置适当的全局和覆盖日志级别如前所述将Microsoft和System的日志级别调高。使用异步Sink大多数Sink如File, Elasticsearch都提供异步版本例如Serilog.Sinks.Async包装器可以将日志写入操作转移到后台线程避免阻塞主业务逻辑。// 安装 Serilog.Sinks.Async 包 .WriteTo.Async(a a.File(logs/app.log)) .WriteTo.Async(a a.Elasticsearch(elasticsearchSinkOptions))配置日志文件滚动和保留策略对于File SinkrollingInterval按时间滚动和retainedFileCountLimit保留文件数是必须配置的。在Elasticsearch端配置索引生命周期管理对于按时间滚动的ES索引可以设置ILM策略自动将旧索引转移到冷存储或直接删除。4.4 与应用程序指标和追踪集成在现代可观测性体系中日志、指标和追踪是三大支柱。它们需要协同工作。与OpenTelemetry集成你可以配置Serilog将日志发送到OpenTelemetry Collector再由Collector统一导出到各种后端。这需要用到Serilog.Sinks.OpenTelemetry这样的Sink。在日志中注入追踪ID如果你使用了分布式追踪如通过OpenTelemetry或Activity可以创建一个Enricher从当前Activity中获取TraceId和SpanId并添加到日志属性中。这样在Kibana或类似的工具中你可以通过追踪ID轻松关联起一个请求的所有日志和跨度信息。public class TraceIdEnricher : ILogEventEnricher { public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) { var activity Activity.Current; if (activity ! null) { logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty(TraceId, activity.TraceId)); logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty(SpanId, activity.SpanId)); } } }将日志系统从简单的“记录文本”升级为“管理结构化事件数据”是提升应用可维护性和可观测性的关键一步。Serilog与ASP.NET Core的深度集成使得这一过程变得异常顺畅。从基础的JSON文件输出到强大的Elasticsearch集中式日志平台Serilog提供了灵活而坚实的阶梯。记住好的日志不是事后才想起的补救措施而应该是在项目伊始就精心设计的基础设施。它会在无数个需要排查问题的时刻成为你最得力的助手。在实际项目中不妨从为关键业务流添加结构化的上下文日志开始逐步构建起属于你自己应用的、脉络清晰的“黑匣子”。

相关新闻

AVIF格式Photoshop插件解决方案:从入门到精通

AVIF格式Photoshop插件解决方案:从入门到精通

AVIF格式Photoshop插件解决方案:从入门到精通 【免费下载链接】avif-format An AV1 Image (AVIF) file format plug-in for Adobe Photoshop 项目地址: https://gitcode.com/gh_mirrors/avi/avif-format 一、为什么AVIF格式插件值得选择 1.1 技术特性解析 …

2026/5/17 3:24:50 阅读更多 →
对比实验:Granite TimeSeries FlowState R1 vs 传统统计模型在股价预测上的效果

对比实验:Granite TimeSeries FlowState R1 vs 传统统计模型在股价预测上的效果

对比实验:Granite TimeSeries FlowState R1 vs 传统统计模型在股价预测上的效果 最近在折腾时间序列预测,特别是金融数据这块,发现大家讨论的热点已经从传统的ARIMA、Prophet这些模型,慢慢转向了像Granite TimeSeries FlowState …

2026/7/5 15:00:06 阅读更多 →
Ollama部署granite-4.0-h-350m效果集:12语种问答+代码补全+函数调用真实截图

Ollama部署granite-4.0-h-350m效果集:12语种问答+代码补全+函数调用真实截图

Ollama部署granite-4.0-h-350m效果集:12语种问答代码补全函数调用真实截图 1. 模型能力全景展示 granite-4.0-h-350m是一个让人惊喜的轻量级指令模型,虽然只有3.5亿参数,但在多语言理解、代码生成和函数调用方面表现出色。这个模型由IBM开发…

2026/7/5 6:29:02 阅读更多 →

最新新闻

OpenCV 4.8 双目立体匹配实战:BM/SGBM/GC 3种算法在Middlebury数据集上的精度与速度对比

OpenCV 4.8 双目立体匹配实战:BM/SGBM/GC 3种算法在Middlebury数据集上的精度与速度对比

OpenCV 4.8 双目立体匹配实战:BM/SGBM/GC算法在Middlebury数据集上的精度与速度对比双目立体视觉作为三维重建的核心技术之一,其核心挑战在于如何高效准确地计算左右图像间的视差图。OpenCV作为计算机视觉领域的瑞士军刀,提供了Block Matchin…

2026/7/6 0:07:19 阅读更多 →
Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C 运行时库一键安装终极指南:告别DLL缺失烦恼 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况:下载了…

2026/7/6 0:05:19 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
免费二维码修复工具终极指南:三步拯救损坏二维码

免费二维码修复工具终极指南:三步拯救损坏二维码

免费二维码修复工具终极指南:三步拯救损坏二维码 【免费下载链接】qrazybox QR Code Analysis and Recovery Toolkit 项目地址: https://gitcode.com/gh_mirrors/qr/qrazybox 你是否曾经面对一个损坏的二维码束手无策?模糊、破损、打印质量差的二…

2026/7/5 23:59:17 阅读更多 →
AsrTools:如何用一款开源工具在5分钟内完成专业级语音转文字?

AsrTools:如何用一款开源工具在5分钟内完成专业级语音转文字?

AsrTools:如何用一款开源工具在5分钟内完成专业级语音转文字? 【免费下载链接】AsrTools ✨ AsrTools: Smart Voice-to-Text Tool | Efficient Batch Processing | User-Friendly Interface | No GPU Required | Supports SRT/TXT Output | Turn your au…

2026/7/5 23:57:17 阅读更多 →

日新闻

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C 运行时库一键安装终极指南:告别DLL缺失烦恼 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况:下载了…

2026/7/6 0:05:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻