详解.NET Core中的数据保护组件(2)

这里我们定义了一个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特性。

运行代码之后,代码和之前的效果一样。

源码地址:

您可能感兴趣的文章:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdsjdz.html