详解.NET Core中的数据保护组件
 更新时间:2018年09月30日 11:23:16   作者:LamondLu  

在本篇文章中我们给大家整理了关于返回主页.NET Core中的数据保护组件的相关知识点内容,有兴趣的朋友们参考下。

背景介绍
在 OWASP(开放式 Web 应用程序安全项目) 2013 年发布的报告中,将不安全的直接对象引用(Insecure Direct Object Reference)标记为 十大 Web 应用程序风险之一, 其表现形式是对象的引用(例如数据库主键)被各种恶意攻击利用, 所以对于Api返回的各种主键外键ID, 我们需要进行加密。

.NET Core 的数据保护组件
.NET Core 中内置了一个IDataProtectionProvider接口和一个IDataProtector接口。其中IDataProtectionProvider是创建保护组件的接口,IDataProtector是数据保护的接口。开发人员可以实现这 2 个接口,创建数据保护组件。
内置的数据保护组件
.NET Core 中默认提供了一个数据保护组件, 下面我们来尝试使用这个默认组件来保护我们的数据。

例: 当前我们有一个Movie类,代码如下, 我们期望当获取Movie对象的时候,Id字段是加密的。

public class Movie
{
public Movie(int id, string title)
{
Id = id;
Title = title;
}

public int Id { get; set; }
public string Title { get; set; }
}

首先我们需要在Startup.cs中ConfigureService方法中配置使用默认的数据保护组件。

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDataProtection();
}

这段代码会启用.NET Core默认的数据保护器。

然后我们创建一个MoviesController, 并在构造函数中注入IDataProtectionProvider对象, 然后使用这个Provider对象创建一个实现IDataProtector接口的数据保护器对象

[Route(“movies”)]
public class MoviesController : Controller
{
private readonly IDataProtector protector;

public MoviesController(IDataProtectionProvider provider)
{
this.protector = provider.CreateProtector(“protect_my_query_string”);
}
}

TIPS: 使用Provider创建Protector的时候,我们传入了一个参数”protect_my_query_string”, 这个参数标明了这个保护器的用途,你也可以把它就当成这个保护器的名字。

注意: 不同用途的保护器不能解密对方的加密字符串。, 如果使用了保护器A去解密保护器B生成的字符串,会产生以下异常CryptographicException: The payload was invalid.

然后我们在MovieController中添加2个Api, 一个是获取所有Movies对象的,一个是获取指定Movie对象的

[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 orignalId = int.Parse(this.protector.Unprotect(id));

var model = GetMovies();

var outputModel = model.Where(item => item.Id == orignalId);

return Ok(outputModel);
}

代码解释

在获取Movie列表的api中,我们使用了IDataProtector接口的Protect方法对Id字段进行了加密
相应的在获取单个Movie对象的api中, 我们需要使用IDataProtector接口的Unprotect方法对Id字段进行解密。

最终效果
首先我们调用/api/movies, 返回结果如下, id字段已经被正确加密了

[{
“id”: “CfDJ8D9KlbQBeipPoQwll5uLR6ygyO6avkgI2teCQGZQShNwsxC9ApDdsnyYd1K5IyNHjhZcRoGd6W31se3W6TWM8H9UdLEPn4fJpS5uKkqUa0PMV6a0ZZHBQSnlGoisSnj29g”,
“title”: “泰坦尼克号”
}, {
“id”: “CfDJ8D9KlbQBeipPoQwll5uLR6wkMUYyzflIzy3CwoMhcaO-np2WOy4czIL3WZd2FWi7Tsy119tDeFq7yAeye4o2W-KmbffpGXnTDZzNv2QbCrAm7-AyEN35g3pkfAYHa3X7aQ”,
“title”: “我是谁”
}, {
“id”: “CfDJ8D9KlbQBeipPoQwll5uLR6x2AXM6ulCwts2-uQSfzIU8UquTz-OAZIl-49D5-CYYl5H4mfZH8VihhCBJ60MMrZOlZla9qvb8EIP6GYRkEap4nhktbzGxW0Qu5r3edm6_Kg”,
“title”: “蜘蛛侠”
}, {
“id”: “CfDJ8D9KlbQBeipPoQwll5uLR6zDZeLtPIVlkRLCd_V6Mr2kTzWsCkfYgmS0-cqhFAOu4dUWGtx6d402_eKnObAOFUClEDdF4mrUeDQawE71DDa805umhbAvX2712i7UgYO5MA”,
“title”: “钢铁侠”
}]

然后我们继续调用api, 查询钢铁侠的电影信息

/api/movies/CfDJ8D9KlbQBeipPoQwll5uLR6zDZeLtPIVlkRLCd_V6Mr2kTzWsCkfYgmS0-cqhFAOu4dUWGtx6d402_eKnObAOFUClEDdF4mrUeDQawE71DDa805umhbAvX2712i7UgYO5MA

结果也正确的返回了。

[{“id”:4,”title”:”钢铁侠”}]

带过期时间的数据保护器(Limited Lifetime)
.NET Core默认还提供了一种带过期时间的数据保护器, 这种数据保护器许多使用场景,最常用的场景就是当为一个重置密码操作的Token设置失效时间, 这样一旦超时的, Token就不能解密成功, 从而我们就可以认定重置密码操作超时了。

.NET Core中, 我们可以使用IDataProtector接口的ToTimeLimitedDataProtector方法创建一个带过期时间的数据保护器。

这里我们还是使用默认还是继续以上面的例子为例, 代码修改如下

private readonly ITimeLimitedDataProtector protector;

public MoviesController(IDataProtectionProvider provider)
{
this.protector = provider.CreateProtector(“protect_my_query_string”)
.ToTimeLimitedDataProtector();
}

[HttpGet]
public IActionResult Get()
{
var model = GetMovies(); // simulate call to repository

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);
}

代码解释

这里我们定义了一个ITimeLimitedDataProtector接口对象protector, 并在构造函数中使用ToTimeLimitedDataProtector方法,将一个普通的数据保护器转换成了一个带过期时间的数据保护器
在获取Movie列表的api中, 我们依然使用Protect方法来加密Id字段, 与之前不同的是,这里我们加入了第二个TimeSpan参数,这个参数表示了当前加密的有效时间只有10秒。

最终效果
现在我们重新运行项目,还是和之前一样先调用/api/movies方法来获取Movies列表, 结果如下

[{
“id”: “CfDJ8D9KlbQBeipPoQwll5uLR6yzbDbZ931toH32VC6Jqg8DWsrmiLrOxOFFViH4QWZne43jwSVzBjzJIfctYKZniZKNVbr50RRIZpW2fe9UtPajEzBhI-H32Effm-F0ColUaA”,
“title”: “泰坦尼克号”
}, {
“id”: “CfDJ8D9KlbQBeipPoQwll5uLR6zDDVymvftZK9lKBIjEyuoNTzOEu0SC2-qfTy6quXir2S8f3A1r44f9Yz3Sd_cyLZUp-_4gfJAasMfE8_ngYLrJmdsjN9LZ0g4vox0WJLjiGA”,
“title”: “我是谁”
}, {
“id”: “CfDJ8D9KlbQBeipPoQwll5uLR6zL-M2jzv2HCeTiHjevkXvI2216NERplp43TOjCXtj4S52ll68sLyQNtG2FhhWlsOmFGvYY5G4gm5SKfASMMgE1jBr20xc2b_djWdLhWLIxnA”,
“title”: “蜘蛛侠”
}, {
“id”: “CfDJ8D9KlbQBeipPoQwll5uLR6wAoZKCHTG0lvgYS3If_0_eAD30a2YV8RjNagwLXUdCSKsO3kyS58hqDqAPHw_KHwNpd-hjDFl3hFPa8LOWHyk901oc6ZuSxwzxFlljaVreFA”,
“title”: “钢铁侠”
}]

等待10秒钟后,我们继续调用api, 查询钢铁侠的电影信息

/api/movies/CfDJ8D9KlbQBeipPoQwll5uLR6wAoZKCHTG0lvgYS3If_0_eAD30a2YV8RjNagwLXUdCSKsO3kyS58hqDqAPHw_KHwNpd-hjDFl3hFPa8LOWHyk901oc6ZuSxwzxFlljaVreFA

返回了错误信息CryptographicException: The payload expired at 9/29/2018 11:25:05 AM +00:00. 这说明当前加密的有效期已过, 不能正确解密了。

Tips: 使用Action Filter解密参数
在之前的代码中,我们在获取单个Movie的方法中,我们手动调用了Unprotected方法来解密id属性

[HttpGet(“{id}”)]
public IActionResult Get(string id)
{
var orignalId = int.Parse(this.protector.Unprotect(id));

var model = GetMovies(); // simulate call to repository

var outputModel = model.Where(item => item.Id == orignalId);

return Ok(outputModel);
}

下面我们改用Action Filter来改进这部分代码。

首先我们创建一个DecryptReferenceFilter, 代码如下:

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))
{ }
}

代码解释

这里DecryptReferenceFilter实现了IActionFilter接口, 并实现了OnActionExecuting和OnActionExecuted方法
在DecryptReferenceFilter类中,我们注入了默认的数据保护器提供器,并在构造函数中初始化了一个数据保护器
在OnActionExecuting中我们从RouteData中获取到未解密的id字段, 然后将其解密之后,替换了之前未解密的id字段,这样ModelBinder就会使用解密后的字符串来绑定模型。

最终修改
最后我们修改一下获取单个Movie的api, 代码如下:

[HttpGet(“{id}”)]
[DecryptReference]
public IActionResult Get(int id)
{
var model = GetMovies();

var outputModel = model.Where(item => item.Id == id);

return Ok(outputModel);
}

我们在获取单个Movie的方法上添加了DecryptReference特性。

运行代码之后,代码和之前的效果一样。
源码地址:xiazai.jb51.net/201809/yuanma/id_protector_jb51.rar

您可能感兴趣的文章:vue3.0搭配.net core实现文件上传组件ASP.NET Core MVC学习之视图组件(View Component).NET Core 3.0之创建基于Consul的Configuration扩展组件.net core高吞吐远程方法如何调用组件XRPC详解.net core如何利用ConcurrentTest组件对方法进行压力测试详解详解.Net Core中的日志组件(Logging)详解.Net core2.0日志组件Log4net、Nlog简单性能测试.Net Core学习教程之在Mvc中简单的使用日志组件基于.net的分布式系统限流组件示例详解.NET程序集引用COM组件MSScriptControl遇到问题的解决方法.NET 开源配置组件 AgileConfig的使用简介

.NET
Core

相关文章
ASP.NET+XML打造网络硬盘原理分析文件传送常用的三种方式:FTP、Email及网上邻居,都在一定程度上实现了文件数据的交流,但它们都主要面向“点对点”的传送,无法实现一块空间,资源互见的应用需求,这种基于点对多的共享模式需要寻求另外的传输途径,网络硬盘就是一种很好的解决方式 2012-09-09
Visual Studio 2017正式版发布 Mac版新功能特性有哪些Visual Studio 2017正式版推出时间什么时候?Mac版新功能特性又有哪些?这篇文章就为大家详细介绍Visual Studio 2017正式版的最新消息,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 2017-03-03
Linux(Ubuntu)下搭建ASP.NET Core环境本文给大家介绍的是无需安装mono,在Linux(Ubuntu14.04.4 LTS)下搭建ASP.NET Core环境 继续.NET跨平台,希望对大家能够有所帮助。 2016-07-07
win2003服务器.NET+IIS环境常见问题排障总结在使用iis运行asp.net环境的时候,总是会或多或少的碰到各种各样的.net运行错误,这里特别从网络整理了下,方便需要的朋友。 2011-08-08
asp.net关于onpropertychange和oninput事件实现代码文本框,数据列表,当在文本框中输入条件时需要实时刷新数据列表,而且需要满足多浏览器(IE6.0/7.0/8.0,FireFox,Opera,google chrome,Safair)其功能类似google的智能匹配,我是用asp.net实现的。
2009-11-11
拥有网页版小U盘 ASP.NET实现文件上传与下载功能这篇文章主要为大家详细介绍了ASP.NET实现文件上传与下载功能,类似于U盘功能,具有一定的参考价值。感兴趣的小伙伴们可以参考一下 2016-08-08
自己常用到的自定义公共类(已测试通过)自己常用到的自定义公共类(已测试通过)… 2007-03-03
ASP.NET MVC自定义错误页面真的简单吗?ASP.NET MVC自定义错误页面真的简单吗?这篇文章主要介绍了ASP.NET MVC自定义错误页面,感兴趣的小伙伴们可以参考一下 2016-10-10
ASP.NET生成eurl.axd Http异常错误的处理方法在IIS6中同时启用了ASP.NET 2.0 和 ASP.NET 4.0 后,网站程序可能会出现如下错误:“ System.Web.HttpException: Path ‘//eurl.axd/‘ was not found. ” 2011-05-05
asp.net中穿透Session 0 隔离(一)服务(Service)对于大家来说一定不会陌生,它是Windows 操作系统重要的组成部分。我们可以把服务想像成一种特殊的应用程序,它随系统的“开启~关闭”而“开始~停止”其工作内容,在这期间无需任何用户参与 2012-11-11

最新评论

声明:本站(华域联盟www.cnhackhy.com)所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。