ASP.NET Core 資料保護(DataProtector) 介紹

簡單來說 DataProtector 就是將加密解密的功能封裝,讓我們可以很方便的儲存資料。

ASP.NET Core 在使用 DataProtector 前需要在 Program.cs 中註冊服務:
    
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDataProtection();

var app = builder.Build();
    

使用示範:
    
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;


[ApiController]
[Route("[controller]")]
public class TestController: ControllerBase
{
    private readonly IDataProtector _dataProtector;

    public TestController(IDataProtectionProvider dataProtectionProvider)
    {
        _dataProtector = dataProtectionProvider.CreateProtector("TestController");
    }
    
    [HttpGet]
    public IActionResult Privacy()
    {
        // 原始資料
        string originalData = "original data";

        // 加密結果
        string protectedData = _dataProtector.Protect(originalData);
        Console.WriteLine($"Protected Data: {protectedData}");

        // 解密結果
        string unprotectedData = _dataProtector.Unprotect(protectedData);
        Console.WriteLine($"Unprotected Data: {unprotectedData}");

        return Ok();
    }
}
    

在上面程式碼中 dataProtectionProvider.CreateProtector 中傳入的字串可以簡單的理解為功能名稱,在不同的功能中會使用不同的加解密金鑰,不同功能無法相互解密資料。

限時資料

DataProtector 還有一個很有趣的功能,就是加上時間限制,例如在下面的加密示範中加上 1 秒的時間限制,馬上解會解的開,但是時間到後再嘗試解開就會出現 System.Security.Cryptography.CryptographicException 例外:
    
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;


[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
    private readonly IDataProtector _dataProtector;

    public TestController(IDataProtectionProvider dataProtectionProvider)
    {
        _dataProtector = dataProtectionProvider.CreateProtector("TestController");
    }

    [HttpGet]
    public IActionResult Privacy()
    {
        // 原始資料
        string originalData = "original data";
        var timeLimitedProtector = _dataProtector.ToTimeLimitedDataProtector();

        // 加密結果
        var timeLimitedData = timeLimitedProtector.Protect(originalData, lifetime: TimeSpan.FromSeconds(1));
        
        // 解密結果
        var timedUnprotectedData = timeLimitedProtector.Unprotect(timeLimitedData);
        Console.WriteLine(timedUnprotectedData);
        
        Thread.Sleep(2_000);
        try
        {
            var anotherTimedUnprotectTry = timeLimitedProtector.Unprotect(timeLimitedData);
        }
        catch (System.Security.Cryptography.CryptographicException e)
        {
            Console.WriteLine("資料已過期");
            throw;
        }

        return Ok();
    }
}
    

範例錯誤訊息如下:
    
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
      System.Security.Cryptography.CryptographicException: The payload expired at 2024/7/30 下午 04:08:56 +00:00.
         at Microsoft.AspNetCore.DataProtection.TimeLimitedDataProtector.UnprotectCore(Byte[] protectedData, DateTimeOffset now, DateTimeOffset& expiration)
    



參考資料:
Microsoft.Learn - Consumer APIs overview for ASP.NET Core
Microsoft.Learn - IDataProtector Interface

留言

張貼留言

如果有任何問題、建議、想說的話或文章題目推薦,都歡迎留言或來信: a@ruyut.com