首頁  >  文章  >  後端開發  >  ASP.NET Core 資料保護(Data Protection)

ASP.NET Core 資料保護(Data Protection)

高洛峰
高洛峰原創
2016-12-26 10:48:371798瀏覽

API 介面 

ASP.NET Core Data Protectio 主要對普通開發人員提供了兩個接口,IDataProtectionProvider 和 IDataProtector。
 我們先來看看這兩個介面的關係:

namespace Microsoft.AspNetCore.DataProtection
{
 //
 // 摘要:
 //  An interface that can provide data protection services.
 public interface IDataProtector : IDataProtectionProvider
 {
 
  byte[] Protect(byte[] plaintext);
 
  byte[] Unprotect(byte[] protectedData);
 }
}

   

可以看到,IDataProtector繼承自IDataProtectionProvider ,並且提供了兩個方法 Protect 和 Unprotect ,從命名來看,一個是加密,一個是解密。而他們的簽章都是傳入一個byte數組,這也意味著他們可以加密、解密一切物件。返回的也是byte數組,也就是說在實際的使用過程中,我們應該自己添加或使用系統的一些擴展方法來具體化我們的需求。 

我們再看一下IDataProtectionProvider介面:

namespace Microsoft.AspNetCore.DataProtection
{
 public interface IDataProtectionProvider
 {
 
  IDataProtector CreateProtector(string purpose);
 }
}

   

IDataProtectionProvider提供了一個方法,透過傳入一個 purposeose(請參閱後面詳細介紹)來產生一個IDataProt介面物件。
 從這個介面的命名來看,它以Provider結尾,也就是說這部分我們可以實現自己的一套加解密的東西。 

我們在閱讀微軟專案的原始碼的時候,常常看著一些以xxxxProvider結尾的對象,那麼它的職責是什麼,同時扮演什麼樣的角色呢?
 其實這是微軟專門為ASP.NET設計的一個設計模式,叫Provider Model設計模式,也可以說它是由微軟發明的,它不屬於23種設計模式中的一種,從功能上來看的話,應該是工廠和策略的結合。自ASP.NET 2.0開始,微軟就開始引入這種設計模式,最開始主要是用於實現應用程式的配置的多個實作。例如開發者最熟悉的web.config中, 針對於資料庫連接字串的配置, 還有二進制,再比如XML啊等等很多,現在其他地方這種模式也用的越來越多起來。

再來說一下CreateProtector方法簽名中的purpose 這個字串,在上一篇博文中為了讀者好理解,我把傳入的purpose說成可以理解為一個公鑰,其實這個說法是不嚴謹的,可以理解為一個標識,指示目前Protector的用途。

在使用IDataProtector的時候,會發現它還有一些擴充方法位於Microsoft.AspNetCore.DataProtection命名空間下:

public static class DataProtectionCommonExtensions
{
 public static IDataProtector CreateProtector(this IDataProtectionProvider provider, IEnumerable<string> purposes);
 
 public static IDataProtector CreateProtector(this IDataProtectionProvider provider, string purpose, params string[] subPurposes);
 
 public static IDataProtector GetDataProtector(this IServiceProvider services, IEnumerable<string> purposes);
 
 public static IDataProtector GetDataProtector(this IServiceProvider services, string purpose, params string[] subPurposes);
 
 public static string Protect(this IDataProtector protector, string plaintext);
 
 public static string Unprotect(this IDataProtector protector, string protectedData);
}

   


(IEnumerable,params string[]),為什麼會有這種需求呢? 


其實DataProtector是有層次結構的,再看一下IDataProtector接口,它自身也實現了IDataProtectionProvider接口,就是說IDataProtector自身也可以再創建IDataProtector。 


舉個例子:我們在做一個訊息通訊的系統,在訊息通訊的過程中,需要對使用者的會話進行加密,我們使用CreateProtector("Security.BearerToken")加密。但是加密的時候並不能保證訊息是不受信任的客戶端發過來的,所以想到了CreateProtector("username")來進行加密,這個時候假如有一個用戶的用戶名叫“Security.BearerToken”,那麼就而另一個使用Security.BearerToken作為標示的Protector 衝突了,所以我們可以使用

 CreateProtector([ “Security.BearerToken”, “User: username” ])這種方式。它相當於
 provider.CreateProtector(“Security.BearerToken).CreateProtector(“User: username”)。意思是先建立一個Protector叫“Security.BearerToken”,然後再在purpose1下建立一個名為“User: username”的Protector。

有些時候,我們需要一些具有過期或到期時間的加密字串,例如一個用戶在找回密碼的時候,我們向用戶的郵箱發送一封帶有重置命令的一封郵件,這個重置命令就需要有一個過期時間了,超過這個過期時間後就失效,在以前我們可能需要向數據庫存儲一個時間來標記發送時間,然後再解密對比和數據庫的時間差來驗證。這麼做了,ASP.NET Core 預設提供了一個介面叫做ITimeLimitedDataProtector ,我們先看一下這個介面的定義:

CreateProtector(string purpose) : ITimeLimitedDataProtector This API is similar to the existing IDataProtectionProvider.CreateProtector in that it can be used to create purpose chains from a root time-limited protector.
Protect(byte[] plaintext, DateTimeOffset expiration) : byte[]
Protect(byte[] plaintext, TimeSpan lifetime) : byte[]
Protect(byte[] plaintext) : byte[]
Protect(string plaintext, DateTimeOffset expiration) : string
Protect(string plaintext, TimeSpan lifetime) : string
Protect(string plaintext) : string

   


ITimeLimitedDataProtector提供了數個重週期方法的用來設定一個重週期的加密方法,使用者可以透過Date TimeOffset,TimeSpan等參數來設定時間。 。

在我们的 ASP.NET Core 运行的时候,系统会基于当前机器的运行环境默认配置一些关于 Data Protection 的东西,但是有些时候可能需要对这些配置做一些改变,比如在分布式部署的时候,在上一篇博文的末尾也提到过,下面就来看一下具体怎么配置的吧。 

上篇文章已经提到过,我们通过以下方式来把 Data Protection 注册到服务中:

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

   


其中AddDataProtection 返回的是一个 IDataProtectionBuilder 接口,这个接口提供了一个扩展方法PersistKeysToFileSystem() 来存储私钥。可以通过它传入一个路径来指定私钥存储的位置:

public void ConfigureServices(IServiceCollection services)
{
 services.AddDataProtection()
  .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
 
}

   

可以传入一个共享文件夹,来存储私钥,这样在不同机器的私钥就可以保存到一个位置了。可以通过此种方式在分布式部署的时候,隔离开了机器的差异化。
 如果你觉得不安全,还可以配置一个X.509证书来,进行加密:

public void ConfigureServices(IServiceCollection services)
{
 services.AddDataProtection()
  .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
  .ProtectKeysWithCertificate("thumbprint");
}

   


上篇文章讲过,Data Protection 的默认保存时间是90天,你可以通过以下方式来修改默认的保存时间:

public void ConfigureServices(IServiceCollection services)
{
 services.AddDataProtection()
  .SetDefaultKeyLifetime(TimeSpan.FromDays(14));
}

   


默认情况下,即使使用相同的物理密钥库,Data Protection 也会把不同的应用程序隔离开,因为这样可以防止从一个应用程序获取另外一个应用程序的密钥。所以如果是相同的应用程序,可以设置相同的应用程序名称:

public void ConfigureServices(IServiceCollection services)
{
 services.AddDataProtection()
  .SetApplicationName("my application");
}

   


有时候需要禁用应用程序生成密钥,或者是说我只有一个程序用来生成或者管理密钥,其他程序只是负责读的话,那么可以这样:

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

   


修改加密算法 

可以使用UseCryptographicAlgorithms方法来修改ASP.NET Core Data Protection的默认加密算法,如下:

services.AddDataProtection()
.UseCryptographicAlgorithms(new AuthenticatedEncryptionSettings()
{
 EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
 ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
});

   


总结:

本篇主要是介绍了一些常用的API, 下篇介绍一些高级的用法。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持PHP中文网。

更多ASP.NET Core 数据保护(Data Protection)相关文章请关注PHP中文网!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn