一、为什么DotNetCore应用需要安全防护

开发一个DotNetCore应用就像盖房子,如果只关注功能实现而忽略安全防护,相当于没装防盗门就入住。黑客们可不会客气,他们会尝试各种手段入侵你的系统,比如SQL注入、跨站脚本(XSS)、CSRF攻击等。

举个真实案例:某电商平台因为未对用户输入做过滤,导致攻击者通过拼接恶意SQL语句,轻松获取了所有用户的账号密码。事后调查发现,开发者只是简单拼接SQL查询字符串,类似这样:

// 危险示例:直接拼接SQL(DotNetCore + SQLServer技术栈)
string query = "SELECT * FROM Users WHERE Username = '" + username + "' AND Password = '" + password + "'";
// 攻击者输入 username = 'admin'-- 时,密码验证就被注释掉了!

二、四大核心攻击防御实战

1. SQL注入防护:参数化查询是底线

永远不要相信用户输入!使用参数化查询可以彻底杜绝SQL注入:

// 安全示例:参数化查询(DotNetCore + Entity Framework Core)
var user = await _context.Users
    .FromSqlInterpolated($"SELECT * FROM Users WHERE Username = {username} AND Password = {password}")
    .FirstOrDefaultAsync();

// 或者使用EF Core的LINQ写法(更推荐)
var user = await _context.Users
    .Where(u => u.Username == username && u.Password == password)
    .FirstOrDefaultAsync();

关联技术:对于Dapper这样的轻量级ORM,同样需要参数化:

// Dapper的正确用法
var user = await connection.QuerySingleOrDefaultAsync<User>(
    "SELECT * FROM Users WHERE Username = @username AND Password = @password",
    new { username, password });

2. XSS防护:输出编码不能少

跨站脚本攻击就像让用户在墙上乱涂乱画,我们必须对输出进行编码:

// Razor页面自动编码(DotNetCore MVC)
<p>@Model.UserComment</p>  <!-- 自动HTML编码 -->

// 需要显示HTML时(比如富文本)使用Html.Raw
<p>@Html.Raw(Model.SanitizedHtml)</p> 

对于Web API项目,建议返回纯文本并在前端处理编码:

// API控制器(DotNetCore WebAPI)
[HttpGet]
public IActionResult GetComment()
{
    var comment = _service.GetComment();
    return Ok(new { 
        content = System.Net.WebUtility.HtmlEncode(comment.Content) 
    });
}

3. CSRF防护:验证请求来源

伪造请求就像有人冒充你发快递,防伪标签很重要:

// Startup.cs配置(DotNetCore 3.1+)
services.AddAntiforgery(options => 
{
    options.HeaderName = "X-CSRF-TOKEN";  // 自定义头名称
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});

// 在控制器上添加特性
[AutoValidateAntiforgeryToken]
public class AccountController : Controller

前端需要这样配合:

// 使用axios发送请求时带上token
axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('input[name="__RequestVerificationToken"]').value;

4. 敏感数据保护:加密不是可选项

数据库里存明文密码等于把钥匙插在门上:

// 密码哈希示例(DotNetCore Identity)
var user = new IdentityUser 
{
    UserName = model.Username,
    PasswordHash = new PasswordHasher<IdentityUser>().HashPassword(null, model.Password)
};

// 验证密码
var result = _signInManager.CheckPasswordSignInAsync(user, password, false);

对于配置文件中的敏感信息,推荐使用Azure Key Vault或本地密钥:

// appsettings.json保护(DotNetCore 6.0+)
{
  "ConnectionStrings": {
    "Default": "_db_connection_string_"  // 实际使用机密管理器
  }
}

// 通过命令行设置机密
dotnet user-secrets set "ConnectionStrings:Default" "真实连接字符串"

三、进阶防护策略

1. 请求限流:防止暴力破解

就像ATM输错密码会吞卡,API也要有限制:

// 使用AspNetCoreRateLimit(DotNetCore中间件)
services.AddRateLimiter(options => 
{
    options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(context =>
        RateLimitPartition.GetFixedWindowLimiter(
            partitionKey: context.User.Identity?.Name ?? context.Request.Headers["X-Client-Id"],
            factory: partition => new FixedWindowRateLimiterOptions
            {
                AutoReplenishment = true,
                PermitLimit = 30,
                Window = TimeSpan.FromMinutes(1)
            }));
});

2. CORS策略:不是越开放越好

错误的CORS配置就像把后门敞开:

// 正确的CORS配置(生产环境)
services.AddCors(options =>
{
    options.AddPolicy("ProductionPolicy", builder =>
    {
        builder.WithOrigins("https://trusted-domain.com")
               .AllowAnyHeader()
               .AllowAnyMethod()
               .AllowCredentials();
    });
});

3. 安全头设置:给浏览器的防护盔甲

这些HTTP头就像安全警示牌:

// 使用NWebsec或手动添加中间件
app.Use(async (context, next) =>
{
    context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
    context.Response.Headers.Add("X-Frame-Options", "DENY");
    context.Response.Headers.Add("Content-Security-Policy", 
        "default-src 'self'; script-src 'self' 'unsafe-inline'");
    await next();
});

四、安全监控与应急响应

1. 日志记录:安全事件的监控摄像头

没有日志就像没有监控的银行:

// Serilog配置示例(DotNetCore + ELK技术栈)
Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext()
    .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://elk:9200"))
    {
        AutoRegisterTemplate = true,
        IndexFormat = "dotnetcore-logs-{0:yyyy.MM.dd}"
    })
    .CreateLogger();

// 记录安全事件
_logger.LogWarning("检测到暴力破解尝试,IP:{IP}", HttpContext.Connection.RemoteIpAddress);

2. 漏洞依赖扫描:检查建材质量

使用NuGet包就像用别人的建材,要检查是否安全:

# 使用dotnet-outdated工具
dotnet list package --vulnerable

# 或者使用OWASP Dependency Check
dependency-check.sh --project "MyApp" --scan ./bin/Debug/net6.0

3. 应急响应预案

当真的被攻击时,你需要像消防演习一样的预案:

  1. 立即隔离受影响系统
  2. 保留日志等证据
  3. 评估影响范围
  4. 修复漏洞后再上线
  5. 必要时进行法律维权

应用场景分析

这些防护措施适用于:

  • 电商支付系统(需要最高级别防护)
  • 企业OA系统(中等防护)
  • 内部管理后台(基础防护)
  • 公开API服务(需额外考虑限流)

技术优缺点

✔️ 优点:

  • 分层防御体系
  • 大部分方案DotNetCore原生支持
  • 与现代DevOps流程兼容

❌ 缺点:

  • 部分方案增加系统复杂度
  • 安全校验可能影响性能
  • 需要持续维护更新

注意事项

  1. 不要自己实现加密算法
  2. 定期轮换加密密钥
  3. 生产环境禁用Swagger等调试接口
  4. 关注DotNetCore安全公告
  5. 进行定期的渗透测试

总结

构建安全的DotNetCore应用就像给房子安装安保系统,需要:

  • 基础防护(门窗锁)→ SQL参数化、XSS编码
  • 高级监控(摄像头)→ 日志审计、依赖扫描
  • 应急措施(灭火器)→ 漏洞响应预案

记住:安全不是一次性的工作,而是持续的过程。从今天开始,给你的DotNetCore应用穿上盔甲吧!