ASP.NET Core 数据保护API的使用

在开发Web应用程序时,保护用户数据的安全是非常重要的。ASP.NET Core提供了一个强大的数据保护API,可以帮助开发者在应用程序中实现数据的加密解密。本文将介绍如何在ASP.NET Core应用程序中使用数据保护API来保护敏感数据。

创建项目和更新Startup类

首先,需要创建一个ASP.NET Core项目。然后,需要更新Startup类,以便添加MVC和数据保护服务。

public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddDataProtection(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseMvcWithDefaultRoute(); }

创建模型

接下来,需要创建一个模型,用于表示应用程序中的数据。例如,可以创建一个表示电影的模型。

public class Movie { public int Id { get; set; } public string Title { get; set; } public int ReleaseYear { get; set; } public string Summary { get; set; } }

创建控制器并注入IDataProtectionProvider

然后,需要创建一个控制器,并注入IDataProtectionProvider作为依赖项。这样就可以在控制器中使用数据保护API了。

[Route("movies")] public class MoviesController : Controller { private readonly IDataProtector protector; public MoviesController(IDataProtectionProvider provider) { this.protector = provider.CreateProtector("protect_my_query_string"); } ... }

添加加密和解密方法

在控制器中,需要添加一个方法来检索数据,然后加密对象引用(这里以Id属性为例)。还需要添加一个方法来接收加密的对象引用,然后解密它。

[HttpGet] public IActionResult Get() { var model = GetMovies(); // 模拟调用仓库 var outputModel = model.Select(item => new { Id = this.protector.Protect(item.Id.ToString()), item.Title, item.ReleaseYear, item.Summary }); return Ok(outputModel); } [HttpGet("{id}")] public IActionResult Get(string id) { var originalId = int.Parse(this.protector.Unprotect(id)); var model = GetMovies(); // 模拟调用仓库 var outputModel = model.Where(item => item.Id == originalId); return Ok(outputModel); }

运行示例

运行示例时,访问/movies将显示加密的引用。

讨论

OWASP 2013将不安全的直接对象引用列为十大风险之一。如果对象引用(例如数据库记录的主键)可以被操纵以进行恶意攻击,那么就存在这种风险。

上面的例子展示了一种可能的预防方法,即通过加密内部引用,可以隐藏数据库/应用程序结构的内部细节。可以使用多种方式进行加密,这里使用的是ASP.NET Core中新的数据保护API。

数据保护API

使用两个关键的抽象来加密数据,即IDataProtectionProvider和IDataProtector。使用提供程序通过调用其CreateProtector()方法来创建一个保护器。这个方法接受一个字符串密钥(称为目的字符串)。一旦有了保护器,就可以使用它的Protect()方法来加密和Unprotect()方法来解密数据。

目的字符串

它是一个确保不同保护器(加密消费者)之间隔离的密钥,即,只要它们使用不同的目的字符串,由保护器A加密的数据就不能被保护器B读取。

异常

尝试解密已被修改的数据将抛出CryptographicException。

有限生命周期

还可以加密只能在有限时间内解密的数据(例如,创建密码重置链接的令牌)。为了实现这一点,使用ITimeLimitedDataProtector并指定保护数据的时间周期:

private readonly ITimeLimitedDataProtector protector; public MoviesController(IDataProtectionProvider provider) { this.protector = provider.CreateProtector("protect_my_query_string") .ToTimeLimitedDataProtector(); } [HttpGet] public IActionResult Get() { var model = GetMovies(); // 模拟调用仓库 var outputModel = model.Select(item => new { Id = this.protector.Protect(item.Id.ToString(), TimeSpan.FromSeconds(10)), item.Title, item.ReleaseYear, item.Summary }); return Ok(outputModel); }

提示:动作过滤器

可以创建一个动作过滤器来解密传入的加密引用,这可以在应用程序中重用:

[HttpGet("{id}")] [DecryptReference] public IActionResult Get(int id) { var model = GetMovies(); // 模拟调用仓库 var outputModel = model.Where(item => item.Id == id); return Ok(outputModel); } public class DecryptReferenceFilter : IActionFilter { private readonly IDataProtector protector; public DecryptReferenceFilter(IDataProtectionProvider provider) { this.protector = provider.CreateProtector("protect_my_query_string"); } public void OnActionExecuting(ActionExecutingContext context) { object param = context.RouteData.Values["id"].ToString(); var id = int.Parse(this.protector.Unprotect(param.ToString())); context.ActionArguments["id"] = id; } public void OnActionExecuted(ActionExecutedContext context) { } } public class DecryptReferenceAttribute : TypeFilterAttribute { public DecryptReferenceAttribute() : base(typeof(DecryptReferenceFilter)) { } } public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddDataProtection() .SetApplicationName("Fiver.Security") .PersistKeysToFileSystem(new DirectoryInfo(@"C:\MyKeys")) .SetDefaultKeyLifetime(TimeSpan.FromDays(7)) // 7天是最低 .UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration { EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC, // 默认 ValidationAlgorithm = ValidationAlgorithm.HMACSHA256 // 默认 }); }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485