如何保护 .NET Core API

作者:微信公众号:【架构师老卢】
2-2 10:35
47

概述:了解 C# .NET Core API 安全性将 API 视为连接 Web 应用不同部分的桥梁。就像任何繁忙的桥梁一样,总是存在不速之客的风险。在我们的例子中,这些是喜欢利用任何弱点的黑客。由于 C# .NET Core 广泛用于生成这些桥,因此保护它们非常重要。常见风险SQL注入: 这就像有人偷偷摸摸地把一张纸条塞进你的数据库,诱使它泄露秘密或造成混乱。**跨站点脚本 (XSS):**想象一下,如果有人能把话塞进你的嘴里。XSS 与此类似;黑客可以将自己的脚本放入您的网站,从而对您的用户造成伤害。跨站点请求伪造 (CSRF): 在这里,黑客诱骗用户在他们不知情的情况下在您的网站上做事。这就像

了解 C# .NET Core API 安全性

将 API 视为连接 Web 应用不同部分的桥梁。

就像任何繁忙的桥梁一样,总是存在不速之客的风险。在我们的例子中,这些是喜欢利用任何弱点的黑客。

由于 C# .NET Core 广泛用于生成这些桥,因此保护它们非常重要。

常见风险

  • SQL注入: 这就像有人偷偷摸摸地把一张纸条塞进你的数据库,诱使它泄露秘密或造成混乱。
  • **跨站点脚本 (XSS):**想象一下,如果有人能把话塞进你的嘴里。XSS 与此类似;黑客可以将自己的脚本放入您的网站,从而对您的用户造成伤害。
  • 跨站点请求伪造 (CSRF): 在这里,黑客诱骗用户在他们不知情的情况下在您的网站上做事。这就像在在线表格上伪造签名一样。

现在我们知道了我们要面对的是什么,我们可以开始建立我们的防御。

实现 HTTPS

让我们来谈谈一些关键但经常被忽视的事情 - 在 C# .NET Core API 中实现 HTTPS。

这有点像在你的前门上锁。当然,这是基本的,但它对于确保您的房屋安全至关重要。HTTPS 就是这样为您的数据做的。

简单来说,HTTPS 对在用户浏览器和 API 之间传输的数据进行加密。这就像发送一封只有发送者和接收者才能阅读的秘密信件。

现在让我们来了解实现的基础知识。

1. HSTS(HTTP Strict Transport Security)中间件

HSTS 是一种 Web 安全策略机制,有助于保护网站免受中间人攻击,例如协议降级攻击和 cookie 劫持。

代码示例:

builder.Services.AddHsts(options =>  
{  
    options.Preload = true;  
    options.IncludeSubDomains = true;  
    options.MaxAge = TimeSpan.FromDays(60);  
    options.ExcludedHosts.Add("example.com");  
    options.ExcludedHosts.Add("www.example.com");  
});

此代码片段使用预加载、包含子域和最大期限等选项配置 HSTS 策略。

2. 强制执行 HTTPS 重定向

将所有 HTTP 请求重定向到 HTTPS。这可确保客户端和服务器之间的通信是加密的。

代码示例:

if (!app.Environment.IsDevelopment())  
{  
    app.UseExceptionHandler("/Error");  
    app.UseHsts();  
}  
  
app.UseHttpsRedirection();

此处,用于将所有 HTTP 请求重定向到 HTTPS。app.UseHttpsRedirection();

在 C# .NET Core API 项目中实现这些步骤将确保所有数据在传输过程中都经过加密,从而显著增强其安全性。

身份验证和授权

了解身份验证和授权之间的区别就像了解验证某人是谁和决定他们可以做什么之间的区别一样。让我们来分解一下。

认证

这都是关于验证用户是谁。这就像在门口检查某人的身份证一样。在 ASP.NET Core 中,这由身份验证服务管理,涉及:

  • 对用户进行身份验证。
  • 当未经身份验证的用户尝试访问受限资源时做出响应。

授权

一旦我们知道用户是谁,授权就是确定他们可以访问的内容。这就像根据某人的 ID 级别决定建筑物中的哪些房间可以进入。

身份验证类型

  1. **基于 Cookie 的身份验证:**这种传统的身份验证形式使用存储在用户浏览器中的 cookie。它适用于维护服务器端会话的服务器呈现的应用。
  2. 基于令牌的身份验证: 这包括 JSON Web 令牌 (JWT)。它是无状态的,非常适合现代 Web 应用程序,尤其是单页应用程序 (SPA)。
  3. 第三方认证: 这涉及外部提供商(如Google,Facebook或Microsoft)进行身份验证。

授权类型

  1. 基于角色的授权: 根据用户角色分配权限。具有特定角色的用户有权访问某些资源。
  2. **基于声明的授权:**更精细的是,它允许根据有关用户的特定声明(如年龄、成员身份类型)进行访问。
  3. **基于策略的授权:**最灵活的,允许基于各种因素(如用户、角色、声明甚至请求的上下文)自定义策略。

现在让我们看一些实际的代码示例。

实现身份验证

1. 设置身份验证服务

这是在 中完成的,您可以在其中定义应用程序将使用的身份验证方案。Program.cs

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)  
    .AddJwtBearer(options => builder.Configuration.Bind("JwtSettings", options))  
    .AddCookie(options => builder.Configuration.Bind("CookieSettings", options));

在此示例中,我们设置了 JWT 持有者和 cookie 身份验证方案。

2. 使用认证中间件

中间件至关重要,因为它强制使用已注册的身份验证方案。

var app = builder.Build();  
  
app.UseAuthentication();

此代码注册中间件以使用以前定义的身份验证方案。

实施授权

1. 定义策略或角色

您可以使用属性在控制器中或控制器内定义这些属性。Program.cs

builder.Services.AddAuthorization(options =>  
{  
    options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"));  
});

在此示例中,“AdminOnly”策略仅允许具有“Admin”角色的用户访问某些资源。

2. 申请授权

使用控制器或操作上的属性来强制执行定义的策略或角色。[Authorize]

[Authorize(Policy = "AdminOnly")]  
public IActionResult AdminDashboard()  
{  
    // Controller action code here  
}

此示例使用基于策略的授权来限制对 Admin Dashboard 的访问。

请记住,良好的安全实践是正确识别用户,然后仔细管理他们在应用程序中可以看到和执行的操作。

API 密钥管理

API 密钥管理就像拥有一个特殊的密码来控制谁可以访问您的 API。这对于安全和监视谁在使用你的服务都至关重要。

为什么选择 API 密钥管理?

  1. **安全:**API 密钥充当第一道防线。它们确保只有经过授权的应用程序才能访问您的 API。
  2. **存取控制:**您可以根据每个应用程序分配的密钥来控制和限制每个应用程序可以对 API 执行的操作。
  3. **监控使用情况:**通过跟踪 API 密钥的使用情况,您可以识别模式、检测潜在的滥用行为并做出明智的决策。

让我们看一个基本的实现示例。

1. 生成和存储密钥

首先为每个用户或服务创建唯一密钥。安全地存储这些密钥,最好是存储在数据库中,确保它们已加密。

2. 用于验证的中间件

使用自定义中间件验证每个请求的 API 密钥。中间件应将请求中提供的密钥与系统中存储的密钥进行比较。

public class ApiKeyMiddleware  
{  
    private readonly RequestDelegate _next;  
    private readonly IConfiguration _configuration;  
    private const string ApiKeyHeaderName = "X-API-KEY";  
  
    public ApiKeyMiddleware(RequestDelegate next, IConfiguration configuration)  
    {  
        _next = next;  
        _configuration = configuration;  
    }  
  
    public async Task InvokeAsync(HttpContext context)  
    {  
        if (!context.Request.Headers.TryGetValue(ApiKeyHeaderName, out var extractedApiKey))  
        {  
            context.Response.StatusCode = 401; // Unauthorized  
            await context.Response.WriteAsync("API Key was not provided.");  
            return;  
        }  
  
        var authorizedKey = _configuration\["ApiKey"\];  
        if (authorizedKey != extractedApiKey)  
        {  
            context.Response.StatusCode = 403; // Forbidden  
            await context.Response.WriteAsync("Invalid API Key.");  
            return;  
        }  
  
        await _next(context);  
    }  
}

在此代码片段中,中间件从请求标头中提取 API 密钥,并根据配置的密钥对其进行验证。

3. 配置中间件

在 U 中注册此中间件,以确保为每个 API 调用执行它。Program.cs

app.UseMiddleware<ApiKeyMiddleware>();

最佳实践

  • 定期更新密钥: 定期更改 API 密钥以防止滥用。
  • 限制密钥权限: 为每个密钥分配所需的最少访问权限。
  • 审计和监控: 定期查看密钥使用日志,以检测任何异常或未经授权的访问尝试。

输入验证和清理

输入验证和清理对于保护 API 免受可能危及安全性的恶意输入至关重要。

输入验证和清理的重要性

  1. **安全:**验证和清理输入可防止常见威胁,如 SQL 注入、XSS(跨站点脚本)和其他注入攻击。
  2. **数据完整性:**确保输入符合预期的格式可保持数据的完整性。

实施输入验证和清理

1. 数据注释

利用模型中的数据注释来强制执行验证规则。

public class Product  
{  
    [Required]  
    [StringLength(100, MinimumLength = 3)]  
    public string Name { get; set; }  
  
    [Range(1, 1000)]  
    public decimal Price { get; set; }  
}

此示例使用类似 、 和 的属性来定义产品实体的验证规则。[Required][StringLength][Range]

2. 自定义验证

为标准批注不足的更复杂方案实现自定义验证逻辑。

public class MyCustomValidationAttribute : ValidationAttribute  
{  
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)  
    {  
        // Custom validation logic  
        return ValidationResult.Success;  
    }  
}

3. 消毒输入

对于将在浏览器中呈现的输入(如 Web 应用程序中的用户生成内容),请确保进行清理以防止 XSS 攻击。使用专为清理 HTML 内容而设计的库来去除任何可能有害的脚本。

var sanitizedInput = HtmlSanitizer.Sanitize(input);

4. 模型状态验证

在 API 控制器中,在处理请求之前验证模型状态。

public IActionResult CreateProduct(Product product)  
{  
    if (!ModelState.IsValid)  
    {  
        return BadRequest(ModelState);  
    }  
    // Proceed with processing  
}

为了 API 安全,正确的输入验证和清理是不可协商的。

跨域资源共享 (CORS)

跨域资源共享 (CORS) 是一项安全功能,用于控制 API 响应跨域请求的方式。对于来自不同域的 Web 应用程序访问的 API 来说,这一点至关重要。

了解 CORS

  1. **什么是CORS?**CORS 是一种机制,它根据 HTTP 请求的发起位置允许或限制 Web 服务器上请求的资源。这对于防止对 API 进行不必要的跨域访问至关重要。
  2. **为什么 CORS 很重要?**CORS 可防止因从不同来源不分青红皂白地访问您的 API 而可能产生的安全漏洞。它确保只有受信任的域才能与您的 API 交互。

让我们看一下基本的实现:

1. 配置 CORS

在 或 中定义 CORS 策略:Program.csStartup.cs

builder.Services.AddCors(options =>  
{  
    options.AddPolicy("MyAllowSpecificOrigins",  
    builder =>  
    {  
        builder.WithOrigins("http://example.com",  
                            "http://www.contoso.com")  
               .AllowAnyHeader()  
               .AllowAnyMethod();  
    });  
});

在此示例中,将创建名为“MyAllowSpecificOrigins”的 CORS 策略,该策略允许来自指定源的任何标头和方法。

2. 在中间件中启用 CORS

app.UseCors("MyAllowSpecificOrigins");

这将为您的应用程序启用 CORS 策略。

3. 将 CORS 应用于特定终结点

您还可以将 CORS 策略应用于控制器中的特定终结点:

[EnableCors("MyAllowSpecificOrigins")]  
public class TestController : ControllerBase  
{  
    // Controller actions  
}

使用 CORS 的最佳实践

  • 定义特定来源: 如果可能,请指定确切的来源,而不是使用通配符,以避免意外的跨域访问。
  • **与其他安全措施一起使用:**CORS 应与其他安全实践(如身份验证和输入验证)结合使用。
  • 定期审查政策: 使 CORS 策略与 Web 应用程序不断变化的要求保持同步。

安全标头

正确配置的 HTTP 标头可以增加额外的安全层。本部分将探讨如何在 C# .NET Core API 中实现安全标头。

了解安全标头

  1. 什么是安全标头? 这些是 HTTP 响应标头,设置后,会向浏览器提供指令,以帮助缓解潜在的攻击,如 XSS、点击劫持和其他代码注入攻击。
  2. 为什么它们很重要: 它们增加了额外的保护层,确保浏览器以安全的方式处理来自 API 的内容。

内容安全策略 (CSP)

通过指定允许加载的动态资源来防止 XSS 攻击。

app.Use(async (context, next) =>  
{  
    context.Response.Headers.Add("Content-Security-Policy", "script-src 'self'");  
    await next();  
});

X-内容类型选项

防止 MIME 嗅探攻击。

app.Use(async (context, next) =>  
{  
    context.Response.Headers.Add("X-Content-Type-Options", "nosniff");  
    await next();  
});

还有其他几个:

X-Frame-选项

防止点击劫持。

严格传输安全

强制执行与服务器的安全(HTTP over SSL/TLS)连接。

最佳实践

  • **定期更新政策:**随着威胁的发展,安全标头策略也应如此。
  • 兼容性测试: 确保安全标头不会无意中阻止 API 的合法功能。
  • **结合其他安全实践:**安全标头应是综合安全策略的一部分,包括身份验证、授权、输入验证等。

速率限制和限制

为防止滥用,请务必控制对 API 的请求速率。本部分将讨论如何实现速率限制和限制。

我不会在本文中讨论这个话题,而只是供参考。

保护 C# .NET Core API 需要多方面的方法。

我还建议查看有关此事的 youtube 视频,以了解当今可用的身份验证机制。

例如,JWT、OAuth 等。

常见问题

  1. 在 API 的上下文中,身份验证和授权之间有什么区别? 身份验证是验证用户是谁,而授权是确定用户可以访问哪些资源。
  2. **我应该多久更新一次依赖项以保持 API 安全性?**建议定期检查更新,至少每月检查一次,并及时应用。
  3. **C# .NET Core 是否可以本机处理加密?**是的,C# .NET Core 具有内置库来支持数据加密和解密。
  4. **是否需要对所有 API 实施速率限制?**虽然不是所有 API 都必须这样做,但速率限制是一项有价值的安全措施,尤其是对于面向公众的 API。
  5. 管理 API 密钥的最佳实践是什么? 定期轮换密钥、限制权限、监控使用情况,并在必要时撤销密钥。
相关留言评论
昵称:
邮箱:
阅读排行