我正在尝试使用DI将一个加密/解密类的实例注入ApplicationUser,这是一个用于在MVC6应用程序中保存用户信息的类。但是我错过了一些东西,因为它不起作用。
ApplicationUser类如下所示:
public class ApplicationUser : IdentityUser
{
[FromServices]
[NotMapped]
public StringCrypt Crypt { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string SiteID { get; set; }
[NotMapped]
public string SitePassword {
get
{
bool requiresMigration = false;
bool wasRevoked = false;
return Crypt.Unprotect(SitePW, out requiresMigration, out wasRevoked);
}
set { SitePW = Crypt.Protect(value); }
}
protected string SitePW { get; set; }
}
这是为了支持第三方网站的密码以加密形式存储在数据库中,但可以解密形式透明地访问的情况。
StringCrypt类依赖于内置的ASPNET6数据保护API:
public class StringCrypt : IStringCrypt
{
private IPersistedDataProtector _dp;
public StringCrypt( IDataProtectionProvider dpProvider )
{
_dp = (IPersistedDataProtector) dpProvider.CreateProtector("passwords");
}
public string Unprotect( string protectedData, out bool requiresMigration, out bool wasRevoked )
{
bool ignoreRevocation = true;
byte[] protectedBytes = Convert.FromBase64String(protectedData);
byte[] unprotectedBytes = _dp.DangerousUnprotect(protectedBytes, ignoreRevocation, out requiresMigration, out wasRevoked);
return Encoding.UTF8.GetString(unprotectedBytes);
}
public string Protect( string clearText )
{
byte[] clearBytes = Encoding.UTF8.GetBytes(clearText);
byte[] protectedBytes = _dp.Protect(clearBytes);
string result = Convert.ToBase64String(protectedBytes);
return result;
}
}
我尝试将这一切与内置的依赖注入系统结合在一起,需要对startup.cs中的ConfigureServices方法进行一些调整:
public void ConfigureServices( IServiceCollection services )
{
// normal stuff created by VS2015...
services.AddDataProtection();
// have to avoid setting a file path when we're invoked by dnx
// HostEnvironment is an instance of IHostingEnvironment, set in
// the constructor for Startup
if( (HostEnvironment != null) && (HostEnvironment.WebRootPath != null ) )
services.ConfigureDataProtection(configure =>
{
string pathToCryptoKeys = Path.Combine(HostEnvironment.WebRootPath, "dp_keys");
configure.PersistKeysToFileSystem(new DirectoryInfo(pathToCryptoKeys));
configure.SetDefaultKeyLifetime(TimeSpan.MaxValue);
});
services.AddTransient<StringCrypt>();
}
但是当我运行该站点,并且我在ApplicationUser中进行Crypt.Protect()调用时,它会失败,因为Crypt属性(应该是StringCrypt的一个实例)是未定义的。这意味着它从未被设置......这就是我认为用[FromServices]标记它的方式。
是否以某种方式创建了ApplicationUser的实例来绕过DI系统?或者[FromServices]不能在控制器或视图之外工作?