第十三章 安全实践

news/2026/1/22 21:55:14/文章来源:https://www.cnblogs.com/qxnm/p/19519094

第十三章 安全实践

在微服务架构中,安全不再是单一应用的问题,而是分布式系统的核心挑战。我见过太多团队因为忽视安全而导致数据泄露、服务瘫痪。安全需要从一开始就融入架构设计,而不是事后补救。

13.1 API安全:第一道防线

13.1.1 JWT认证实现

// Program.cs - JWT认证配置
var builder = WebApplication.CreateBuilder(args);// 配置JWT认证
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>{options.TokenValidationParameters = new TokenValidationParameters{ValidateIssuer = true,ValidateAudience = true,ValidateLifetime = true,ValidateIssuerSigningKey = true,ValidIssuer = builder.Configuration["Jwt:Issuer"],ValidAudience = builder.Configuration["Jwt:Audience"],IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:SecretKey"])),ClockSkew = TimeSpan.Zero // 严格的时间验证};// 配置事件处理options.Events = new JwtBearerEvents{OnAuthenticationFailed = context =>{var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Program>>();logger.LogError(context.Exception, "JWT认证失败");return Task.CompletedTask;},OnTokenValidated = context =>{var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Program>>();logger.LogInformation("用户 {User} 认证成功", context.Principal.Identity.Name);return Task.CompletedTask;}};});// 配置授权策略
builder.Services.AddAuthorization(options =>
{// 基于角色的策略options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"));options.AddPolicy("ManagerOrAdmin", policy => policy.RequireRole("Manager", "Admin"));// 基于声明的策略options.AddPolicy("CanCreateOrders", policy =>policy.RequireClaim("permission", "order.create"));// 基于策略的复杂授权options.AddPolicy("SeniorCustomer", policy =>policy.RequireAssertion(context =>{var accountAgeClaim = context.User.FindFirst("account_age_days");if (accountAgeClaim != null && int.TryParse(accountAgeClaim.Value, out var accountAge)){return accountAge >= 365; // 账户至少一年}return false;}));
});// 自定义授权处理程序
public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,MinimumAgeRequirement requirement){var dateOfBirthClaim = context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth);if (dateOfBirthClaim != null && DateTime.TryParse(dateOfBirthClaim.Value, out var dateOfBirth)){var age = DateTime.Today.Year - dateOfBirth.Year;if (dateOfBirth.Date > DateTime.Today.AddYears(-age)) age--;if (age >= requirement.MinimumAge){context.Succeed(requirement);}}return Task.CompletedTask;}
}public class MinimumAgeRequirement : IAuthorizationRequirement
{public int MinimumAge { get; }public MinimumAgeRequirement(int minimumAge){MinimumAge = minimumAge;}
}

13.1.2 API Key认证

// API Key认证中间件
public class ApiKeyAuthenticationMiddleware
{private readonly RequestDelegate _next;private readonly ILogger<ApiKeyAuthenticationMiddleware> _logger;private const string API_KEY_HEADER = "X-API-Key";public async Task InvokeAsync(HttpContext context, IApiKeyService apiKeyService){if (!context.Request.Headers.TryGetValue(API_KEY_HEADER, out var apiKey)){await _next(context);return;}var apiKeyRecord = await apiKeyService.ValidateApiKeyAsync(apiKey);if (apiKeyRecord != null){var claims = new List<Claim>{new Claim(ClaimTypes.Name, apiKeyRecord.ClientName),new Claim("client_id", apiKeyRecord.ClientId),new Claim("api_key_id", apiKeyRecord.Id.ToString())};if (!string.IsNullOrEmpty(apiKeyRecord.Roles)){foreach (var role in apiKeyRecord.Roles.Split(',')){claims.Add(new Claim(ClaimTypes.Role, role.Trim()));}}var identity = new ClaimsIdentity(claims, "ApiKey");context.User = new ClaimsPrincipal(identity);_logger.LogInformation("API Key认证成功: {ClientName}", apiKeyRecord.ClientName);}else{_logger.LogWarning("无效的API Key: {ApiKey}", apiKey);}await _next(context);}
}// API Key服务
public class ApiKeyService : IApiKeyService
{private readonly IDistributedCache _cache;private readonly IConfiguration _configuration;public async Task<ApiKeyRecord> ValidateApiKeyAsync(string apiKey){// 从缓存中查找var cacheKey = $"apikey:{apiKey}";var cached = await _cache.GetStringAsync(cacheKey);if (cached != null){return JsonSerializer.Deserialize<ApiKeyRecord>(cached);}// 从数据库查找(示例)var record = await _dbContext.ApiKeys.Where(k => k.Key == apiKey && k.IsActive && k.ExpiresAt > DateTime.UtcNow).Select(k => new ApiKeyRecord{Id = k.Id,ClientId = k.ClientId,ClientName = k.ClientName,Roles = k.Roles,Permissions = k.Permissions,RateLimit = k.RateLimit,ExpiresAt = k.ExpiresAt}).FirstOrDefaultAsync();if (record != null){// 缓存API Key信息await _cache.SetStringAsync(cacheKey, JsonSerializer.Serialize(record), TimeSpan.FromMinutes(5));}return record;}
}public class ApiKeyRecord
{public Guid Id { get; set; }public string ClientId { get; set; }public string ClientName { get; set; }public string Roles { get; set; }public string Permissions { get; set; }public int RateLimit { get; set; }public DateTime ExpiresAt { get; set; }
}

13.1.3 速率限制实现

// 速率限制中间件
public class RateLimitingMiddleware
{private readonly RequestDelegate _next;private readonly IRateLimitService _rateLimitService;private readonly ILogger<RateLimitingMiddleware> _logger;public async Task InvokeAsync(HttpContext context){var clientId = GetClientIdentifier(context);var rateLimit = await GetRateLimitAsync(context);var requestCount = await _rateLimitService.IncrementRequestCountAsync(clientId, TimeSpan.FromMinutes(1));context.Response.Headers.Add("X-RateLimit-Limit", rateLimit.ToString());context.Response.Headers.Add("X-RateLimit-Remaining", Math.Max(0, rateLimit - requestCount).ToString());if (requestCount > rateLimit){context.Response.Headers.Add("X-RateLimit-Reset", DateTimeOffset.UtcNow.AddMinutes(1).ToUnixTimeSeconds().ToString());context.Response.StatusCode = StatusCodes.Status429TooManyRequests;await context.Response.WriteAsync("请求过于频繁,请稍后再试");_logger.LogWarning("客户端 {ClientId} 超出速率限制: {RequestCount}/{RateLimit}", clientId, requestCount, rateLimit);return;}await _next(context);}private string GetClientIdentifier(HttpContext context){// 优先使用认证用户IDif (context.User.Identity.IsAuthenticated){return context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? context.User.Identity.Name;}// 使用API Keyif (context.Request.Headers.TryGetValue("X-API-Key", out var apiKey)){return $"apikey:{apiKey}";}// 使用IP地址return context.Connection.RemoteIpAddress?.ToString() ?? "unknown";}private async Task<int> GetRateLimitAsync(HttpContext context){// 基于用户角色的速率限制if (context.User.IsInRole("Premium")){return 1000; // 高级用户:1000次/分钟}else if (context.User.IsInRole("Standard")){return 100;  // 标准用户:100次/分钟}// 基于API Key的速率限制if (context.User.Identity.AuthenticationType == "ApiKey"){var apiKeyId = context.User.FindFirst("api_key_id")?.Value;if (apiKeyId != null){var apiKey = await _apiKeyService.GetApiKeyAsync(Guid.Parse(apiKeyId));return apiKey?.RateLimit ?? 60; // 默认60次/分钟}}return 60; // 默认限制}
}// 分布式速率限制服务
public class RedisRateLimitService : IRateLimitService
{private readonly IConnectionMultiplexer _redis;private readonly ILogger<RedisRateLimitService> _logger;public async Task<int> IncrementRequestCountAsync(string clientId, TimeSpan window){var key = $"ratelimit:{clientId}:{DateTime.UtcNow:yyyyMMddHHmm}";var db = _redis.GetDatabase();// 使用Lua脚本确保原子性var script = @"local key = KEYS[1]local window = tonumber(ARGV[1])local current = redis.call('INCR', key)if current == 1 thenredis.call('EXPIRE', key, window)endreturn current";var result = await db.ScriptEvaluateAsync(script, new RedisKey[] { key }, new RedisValue[] { (int)window.TotalSeconds });return (int)result;}
}

13.2 服务间通信安全

13.2.1 mTLS(双向TLS)

# Kubernetes中配置mTLS
apiVersion: v1
kind: ConfigMap
metadata:name: istio-mtls-confignamespace: istio-system
data:mesh: |defaultConfig:proxyMetadata:ISTIO_META_IDLE_TIMEOUT: 30sdefaultProviders:metrics:- prometheusextensionProviders:- name: otelenvoyOtelAls:service: opentelemetry-collector.istio-system.svc.cluster.localport: 4317- name: skywalkingskywalking:service: skywalking-oap.istio-system.svc.cluster.localport: 11800- name: prometheusprometheus:metricsServiceUrl: http://prometheus.istio-system.svc.cluster.local:9090- name: zipkinzipkin:service: zipkin.istio-system.svc.cluster.localport: 9411- name: opentelemetryopentelemetry:port: 4317service: opentelemetry-collector.istio-system.svc.cluster.local- name: otlp-tracingopentelemetry:port: 4317service: opentelemetry-collector.istio-system.svc.cluster.local- name: otlp-metricsopentelemetry:port: 4317service: opentelemetry-collector.istio-system.svc.cluster.local- name: otlp-logsopentelemetry:port: 4317service: opentelemetry-collector.istio-system.svc.cluster.local- name: otlp-tracesopentelemetry:port: 4317service: opentelemetry-collector.istio-system.svc.cluster.local- name: otlp-logsopentelemetry:port: 4317service: opentelemetry-collector.istio-system.svc.cluster.local- name: otlp-tracesopentelemetry:port: 4317service: opentelemetry-collector.istio-system.svc.cluster.local- name: otlp-logsopentelemetry:port: 4317service: opentelemetry-collector.istio-system.svc.cluster.local
---
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:name: defaultnamespace: istio-system
spec:mtls:mode: STRICT
---
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:name: defaultnamespace: ecommerce
spec:mtls:mode: STRICT

13.2.2 服务间认证令牌

// 服务间认证令牌服务
public class InterServiceTokenService
{private readonly IConfiguration _configuration;private readonly IMemoryCache _cache;private readonly HttpClient _httpClient;public async Task<string> GetServiceTokenAsync(string targetService){var cacheKey = $"service_token:{targetService}";// 检查缓存if (_cache.TryGetValue<string>(cacheKey, out var cachedToken)){return cachedToken;}// 创建JWT令牌var token = CreateServiceToken(targetService);// 缓存令牌(提前5分钟过期)var expiration = TimeSpan.FromMinutes(55); // JWT通常1小时过期_cache.Set(cacheKey, token, expiration);return token;}private string CreateServiceToken(string targetService){var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["ServiceToService:SecretKey"]));var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);var claims = new List<Claim>{new Claim("service_id", _configuration["ServiceToService:ServiceId"]),new Claim("service_name", _configuration["ServiceToService:ServiceName"]),new Claim("target_service", targetService),new Claim("purpose", "inter-service-communication")};var token = new JwtSecurityToken(issuer: _configuration["ServiceToService:Issuer"],audience: targetService,claims: claims,expires: DateTime.UtcNow.AddHours(1),signingCredentials: creds);return new JwtSecurityTokenHandler().WriteToken(token);}
}// 服务间HTTP客户端
public class SecureServiceClient
{private readonly HttpClient _httpClient;private readonly InterServiceTokenService _tokenService;private readonly ILogger<SecureServiceClient> _logger;public async Task<T> GetAsync<T>(string serviceName, string endpoint){try{// 获取服务间令牌var token = await _tokenService.GetServiceTokenAsync(serviceName);// 设置认证头_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);var response = await _httpClient.GetAsync($"http://{serviceName}/{endpoint}");response.EnsureSuccessStatusCode();var content = await response.Content.ReadAsStringAsync();return JsonSerializer.Deserialize<T>(content);}catch (Exception ex){_logger.LogError(ex, "服务间调用失败: {ServiceName}/{Endpoint}", serviceName, endpoint);throw;}}
}

13.3 数据安全

13.3.1 数据加密

// 数据加密服务
public class DataEncryptionService
{private readonly byte[] _encryptionKey;public DataEncryptionService(IConfiguration configuration){_encryptionKey = Convert.FromBase64String(configuration["Encryption:Key"]);}public string EncryptSensitiveData(string plainText){using var aes = Aes.Create();aes.Key = _encryptionKey;aes.GenerateIV();using var encryptor = aes.CreateEncryptor();using var ms = new MemoryStream();// 写入IVms.Write(aes.IV, 0, aes.IV.Length);// 写入加密数据using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))using (var sw = new StreamWriter(cs)){sw.Write(plainText);}return Convert.ToBase64String(ms.ToArray());}public string DecryptSensitiveData(string cipherText){var buffer = Convert.FromBase64String(cipherText);using var aes = Aes.Create();aes.Key = _encryptionKey;// 提取IVvar iv = new byte[16];Array.Copy(buffer, 0, iv, 0, 16);aes.IV = iv;// 提取加密数据var encrypted = new byte[buffer.Length - 16];Array.Copy(buffer, 16, encrypted, 0, encrypted.Length);using var decryptor = aes.CreateDecryptor();using var ms = new MemoryStream(encrypted);using var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);using var sr = new StreamReader(cs);return sr.ReadToEnd();}
}// 敏感数据实体
public class Customer
{public Guid Id { get; set; }public string Name { get; set; }public string Email { get; set; }// 加密存储的敏感信息public string EncryptedCreditCard { get; set; }public string EncryptedPhoneNumber { get; set; }[NotMapped]public string CreditCardNumber { get => _encryptionService?.DecryptSensitiveData(EncryptedCreditCard);set => EncryptedCreditCard = _encryptionService?.EncryptSensitiveData(value);}[NotMapped]public string PhoneNumber { get => _encryptionService?.DecryptSensitiveData(EncryptedPhoneNumber);set => EncryptedPhoneNumber = _encryptionService?.EncryptSensitiveData(value);}private DataEncryptionService _encryptionService;public void SetEncryptionService(DataEncryptionService service){_encryptionService = service;}
}

13.3.2 数据脱敏

// 数据脱敏服务
public class DataMaskingService
{public string MaskEmail(string email){if (string.IsNullOrEmpty(email)) return email;var atIndex = email.IndexOf('@');if (atIndex <= 1) return email;var username = email.Substring(0, atIndex);var domain = email.Substring(atIndex);if (username.Length <= 2){return $"{username[0]}***{domain}";}return $"{username.Substring(0, 2)}***{domain}";}public string MaskCreditCard(string creditCard){if (string.IsNullOrEmpty(creditCard) || creditCard.Length < 4)return creditCard;var lastFour = creditCard.Substring(creditCard.Length - 4);return $"****-****-****-{lastFour}";}public string MaskPhoneNumber(string phoneNumber){if (string.IsNullOrEmpty(phoneNumber) || phoneNumber.Length < 7)return phoneNumber;return $"{phoneNumber.Substring(0, 3)}****{phoneNumber.Substring(phoneNumber.Length - 4)}";}public T MaskObject<T>(T obj) where T : class{var masked = Activator.CreateInstance<T>();var properties = typeof(T).GetProperties();foreach (var prop in properties){var value = prop.GetValue(obj);if (value != null){var maskedValue = MaskValue(value.ToString(), prop.Name);prop.SetValue(masked, maskedValue);}}return masked;}private string MaskValue(string value, string propertyName){if (propertyName.Contains("email", StringComparison.OrdinalIgnoreCase))return MaskEmail(value);if (propertyName.Contains("credit", StringComparison.OrdinalIgnoreCase))return MaskCreditCard(value);if (propertyName.Contains("phone", StringComparison.OrdinalIgnoreCase))return MaskPhoneNumber(value);return value;}
}

13.4 安全监控与审计

13.4.1 安全事件日志

// 安全事件类型
public enum SecurityEventType
{AuthenticationSuccess,AuthenticationFailure,AuthorizationSuccess,AuthorizationFailure,TokenValidationFailure,RateLimitExceeded,SuspiciousActivity,DataAccess,ConfigurationChange
}// 安全审计服务
public class SecurityAuditService
{private readonly ILogger<SecurityAuditService> _logger;private readonly IDbContextFactory<AuditDbContext> _dbContextFactory;public async Task LogSecurityEventAsync(SecurityEventType eventType, string userId, string details, object metadata = null){var auditLog = new SecurityAuditLog{Id = Guid.NewGuid(),Timestamp = DateTime.UtcNow,EventType = eventType,UserId = userId,IpAddress = GetClientIpAddress(),UserAgent = GetUserAgent(),Details = details,Metadata = metadata != null ? JsonSerializer.Serialize(metadata) : null};// 记录到数据库await using var dbContext = _dbContextFactory.CreateDbContext();await dbContext.SecurityAuditLogs.AddAsync(auditLog);await dbContext.SaveChangesAsync();// 记录到日志系统var logLevel = eventType switch{SecurityEventType.AuthenticationFailure => LogLevel.Warning,SecurityEventType.AuthorizationFailure => LogLevel.Warning,SecurityEventType.SuspiciousActivity => LogLevel.Error,_ => LogLevel.Information};_logger.Log(logLevel, "安全事件: {EventType} - 用户: {UserId} - {Details}", eventType, userId, details);}public async Task<List<SecurityAuditLog>> GetSecurityEventsAsync(DateTime startDate, DateTime endDate, SecurityEventType? eventType = null){await using var dbContext = _dbContextFactory.CreateDbContext();var query = dbContext.SecurityAuditLogs.Where(l => l.Timestamp >= startDate && l.Timestamp <= endDate);if (eventType.HasValue){query = query.Where(l => l.EventType == eventType.Value);}return await query.OrderByDescending(l => l.Timestamp).Take(1000).ToListAsync();}
}// 安全审计实体
public class SecurityAuditLog
{public Guid Id { get; set; }public DateTime Timestamp { get; set; }public SecurityEventType EventType { get; set; }public string UserId { get; set; }public string IpAddress { get; set; }public string UserAgent { get; set; }public string Details { get; set; }public string Metadata { get; set; }
}

13.4.2 异常行为检测

// 异常行为检测服务
public class AnomalyDetectionService
{private readonly IDistributedCache _cache;private readonly SecurityAuditService _auditService;private readonly ILogger<AnomalyDetectionService> _logger;public async Task CheckForAnomaliesAsync(string userId, SecurityEventType eventType){var key = $"anomaly:{userId}:{eventType}:{DateTime.UtcNow:yyyyMMddHH}";var count = await _cache.IncrementAsync(key, TimeSpan.FromHours(1));// 基于事件类型的阈值var threshold = eventType switch{SecurityEventType.AuthenticationFailure => 5,SecurityEventType.RateLimitExceeded => 10,SecurityEventType.AuthorizationFailure => 20,_ => 50};if (count > threshold){await _auditService.LogSecurityEventAsync(SecurityEventType.SuspiciousActivity,userId,$"检测到异常行为: {eventType} 在1小时内发生 {count} 次",new { Threshold = threshold, ActualCount = count });// 触发告警await TriggerSecurityAlertAsync(userId, eventType, count);}}private async Task TriggerSecurityAlertAsync(string userId, SecurityEventType eventType, int count){var alert = new SecurityAlert{Id = Guid.NewGuid(),Timestamp = DateTime.UtcNow,Severity = AlertSeverity.High,UserId = userId,EventType = eventType,Message = $"用户 {userId} 触发安全告警: {eventType} 发生 {count} 次",Status = AlertStatus.New};// 发送告警到监控系统await _alertingService.SendAlertAsync(alert);_logger.LogError("安全告警触发: {Alert}", alert.Message);}
}

13.5 小结

微服务安全是一个持续的过程,需要在架构的各个层面进行考虑。记住几个关键原则:

  1. 零信任架构 - 不信任任何网络边界,每个请求都需要验证
  2. 最小权限原则 - 只授予必要的权限,及时回收不再需要的权限
  3. 深度防御 - 多层次的安全措施,即使一层被突破还有其他保护
  4. 安全左移 - 在开发阶段就考虑安全问题,而不是部署后
  5. 持续监控 - 实时监控安全事件,及时发现和响应威胁

最重要的是,安全不是一次性的工作,而是需要持续关注和改进的过程。随着威胁环境的变化,安全策略也需要不断演进。

在下一章中,我们将探讨性能优化,确保微服务系统在高负载下仍能保持良好性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1201853.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【课程设计/毕业设计】基于springboot的企业日报管理日报管理系统设计与实现【附源码、数据库、万字文档】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

Linux中批量修改文件名的方法

使用 rename 命令&#xff1a; rename s/\.jpg$/\.png/ *.jpg 这里的s代表替换操作&#xff0c;\.jpg$是匹配.jpg文件名的正则表达式&#xff0c;\.png是新文件名的格式。

第十五章 故障处理与运维

第十五章 故障处理与运维 在微服务架构中,系统的复杂性和分布式特性使得故障处理和运维变得尤为重要。单个服务的故障可能通过服务依赖链扩散,影响整个系统的可用性。因此,构建一个具备高可用性、容错性和可恢复性的…

【课程设计/毕业设计】基于web的饰品商城的设计与实现基于springboot的饰品商城系统【附源码、数据库、万字文档】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

计算机Java毕设实战-基于springboot的日报管理系统设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

第十六章 电商系统微服务实战(完结,总结以及之前所有内容会发到github)

第十六章 电商系统微服务实战 理论学得再多,不如亲手做一个项目。这一章,我将带你从零开始构建一个真实的电商微服务系统。这不是玩具项目,而是考虑了生产环境各种复杂情况的真实案例。 16.1 需求分析与架构设计 16…

Java计算机毕设之基于springboot的日报管理系统设计与实现(完整前后端代码+说明文档+LW,调试定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

Hello World:一个后端程序员的碎碎念与新开始

Hello World! 敲下这行字的时候,感觉就像当年第一次在控制台打印出 Hello World 一样,既熟悉又带着一点仪式感。 作为一个在代码世界里摸爬滚打有些年头的 Java 后端开发,我想是时候搭建一个属于自己的“独立服务器…

计算机Java毕设实战-基于springboot的饰品商城系统基于Java Web的饰品商城系统的设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

从零开始学电脑:新手入门完全指南 - 指南

从零开始学电脑:新手入门完全指南 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "…

2025.12.20 作业 - # P1246 编码

2025.12.20 作业 - # P1246 编码题目描述 编码工作常被运用于密文或压缩传输。这里我们用一种最简单的编码方式进行编码:把一些有规律的单词编成数字。 字母表中共有 \(26\) 个字母 \(\mathtt{a,b,c,\cdots,z}\),这些…

【Da】调色面板

--本篇导航--界面各个调色工具调色节点复制/应用调色Lut界面重置调色抓取静态帧(截图)光箱 就是一个筛选器,会对素材进行各种条件的筛选,方便调色片段的管理。各个调色工具 波形图校色轮HDR色轮RGB混合器运动特效曲…

学习AI编程

habit-tracker 一个不错的AI编程示例。

打开CMD的方法和常用Dos命令

打开CMD的方法开始+系统+命令提示符 Win建+R 输入cmd打开控制台(通常使用) 在任意文件夹下面,按住shift键+鼠标右键点击,在此处打开命令行窗口 资源管理器的地址栏前面加上cmd路径管理员方式运行:选择以管理员方式…

基于 YOLOv8 的水稻病害智能检测系统实战源码【从农田到模型】

基于 YOLOv8 的水稻病害智能检测系统实战源码【从农田到模型】 一、项目背景&#xff1a;为什么要做“水稻病害检测系统”&#xff1f; 在传统农业生产中&#xff0c;病害识别严重依赖人工经验。实际问题主要集中在三点&#xff1a; 巡田成本高&#xff1a;大面积农田靠人工…

【HTML】前端工具箱建立【文本处理/JSON程序/加解密/校验和/ASCII/时间戳转换等】【附完整源代码】

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025.12.20 作业 - # P11951 [科大国创杯初中组 2023] 数数

2025.12.20 作业 - # P11951 [科大国创杯初中组 2023] 数数题目描述 小可可和小多在拼木棍。 他们现在拿到了 \(n\) 根木棍,第 \(i\) 根木棍的长度是 \(a_i\)。他们现在想知道,有多少种在里面选三根木棍的方案,使得…

HRCSA项目结课

一&#xff0c;项目准备1、安装RHEL9系统2、配置系统修改主机名并清除yum数据库配置本地光盘为yum源测试网络连通性二、部署项目1、安装LNMP环境2、配置环境&#xff08;数据库配置&#xff09;&#xff08;2&#xff09;论坛安装文件3、安装论坛软件