Cul*_*tes 11 c# asp.net data-protection asp.net-identity asp.net-core
我遇到了与DataProtectionProvider有关的这个问题,首先我们只有2个.NET Framework项目,现在添加了一个.NET Core项目让我困惑如何执行以下操作:从.NET Framework项目生成密码重置链接,并在.NET Core项目中使用它.两者都使用相同的数据库和用户表,这些表已经相互兼容..NET Framework仍然是Code-First数据库生成中的领先项目.
在两个.NET框架项目中,我使用一个共享代码库,它具有以下代码:
//not sure where I got this from but it is part of the solution for solving
//password link generating and using in two different applications.
public class MachineKeyProtectionProvider : IDataProtectionProvider
{
public IDataProtector Create(params string[] purposes)
{
return new MachineKeyDataProtector(purposes);
}
}
public class MachineKeyDataProtector : IDataProtector
{
private readonly string[] _purposes;
public MachineKeyDataProtector(string[] purposes)
{
_purposes = purposes;
}
public byte[] Protect(byte[] userData)
{
return MachineKey.Protect(userData, _purposes);
}
public byte[] Unprotect(byte[] protectedData)
{
return MachineKey.Unprotect(protectedData, _purposes);
}
}
Run Code Online (Sandbox Code Playgroud)
然后在User Repository中:
private readonly UserManager<ApplicationUser> _userManager = null;
private readonly RoleManager<IdentityRole> _roleManager = null;
internal static IDataProtectionProvider DataProtectionProvider { get; private set; }
public UserRepository(DatabaseContext dbContext)
{
_userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(dbContext));
_roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(dbContext));
_userManager.UserValidator = new UserValidator<ApplicationUser>(_userManager) { AllowOnlyAlphanumericUserNames = false };
if (DataProtectionProvider == null)
{
DataProtectionProvider = new MachineKeyProtectionProvider();
}
_userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser, string>(DataProtectionProvider.Create("Identity"));
}
Run Code Online (Sandbox Code Playgroud)
在两个.NET Framework项目中,我都有一个<machineKey>集合.之后,我可以简单地使用:
public string GeneratePasswordResetCode(string userId)
{
return _userManager.GeneratePasswordResetToken(userId);
}
public void ChangeUserPassword(string oldPassword, string newPassword)
{
string id = InfrastructureUserHelper.User.GetUserId();
IdentityResult result = _userManager.ChangePassword(id, oldPassword, newPassword);
...
}
Run Code Online (Sandbox Code Playgroud)
因此,现在添加了一个.NET Core项目,该项目已经有自己的密码重置机制,但所有自动化作业都是从一个.NET Framework项目发送的.原因是用户应为自动创建的帐户设置密码.
我该怎么做呢?我一直在看这个: https ://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?tabs=aspnetcore2x和this:如何在ASP.NET Core中实现machineKey 2.0
但我无法弄清楚一个简单易行的解决方案.我宁愿避免创建额外的redis服务器.类似于机器钥匙的东西可以完成这项工作.我尝试从这个文档开始,但我无法弄清楚.NET Core项目中的哪个部分以及.NET Framework项目的哪个部分.
到目前为止,我一直试着玩这个部分没有运气:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection().SetApplicationName("Identity")
.SetDefaultKeyLifetime(TimeSpan.FromDays(60))
.ProtectKeysWithDpapi();
services.AddIdentity<ApplicationUser, ApplicationRole>().AddDefaultTokenProviders();
}
Run Code Online (Sandbox Code Playgroud)
编辑: 我最终可以使用我们的Blob存储,看到这个页面:https: //docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?tabs=aspnetcore2x
添加这似乎有点帮助,两个应用程序运行正常但仍然在.NET Framework项目中不使用正确的DataProtectionProvider.UserManager找不到它(没有ITokenProvider错误).
最终我放弃并将令牌存储在用户数据库中完全不理想,但花了很多时间来尝试解决一些无法记录的事情.-1表示微软.
Data Protection API在.NET Framework和.NET Core中的工作方式相同.
使用X509证书而不是旧的机器密钥方法来加密密钥而不是机器密钥.自生成证书很好,因为加密纯粹是供内部使用.
要点:如果您控制服务器,则必须在证书存储中安装证书.使用ProtectWithCertificate接受X509证书实例的重载有一个荒谬的,未记录的捕获:它只能使用该实例进行加密.如果证书不在商店中,则解密失败.微软声称这是"底层框架"的一些限制,无论这意味着什么,但可以使用变通方法(并不复杂).我对此使用了一个变体,并将证书序列化为Azure Key Vault,这样我们就不必触及每个服务器.
您还需要指定一个DPAPI持久性选项,以确保所有服务器都可以访问数据.由于我们使用的是Azure,因此下面的代码使用blob存储,但如果您运行自己的服务器,则可能是网络共享PersistKeysToFileSystem.
我的设置ConfigureServices如下:
var x509 = GetDpApiCert(); // library utility
var container = GetBlobStorageRef(); // library
services.AddDataProtection()
.SetApplicationName(appconfig["DpapiSiteName"])
.ProtectKeysWithProvidedCertificate(x509)
.PersistKeysToAzureBlobStorage(container, appconfig["DpapiFileName"]);
Run Code Online (Sandbox Code Playgroud)
这是我生成证书的Powershell脚本:
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)][string]$password = "",
[Parameter(Mandatory=$true)][string]$rootDomain = ""
)
$cwd = Convert-Path .
$CerFile = "$cwd\aspnet_dpapi.cer"
$PfxFile = "$cwd\aspnet_dpapi.pfx"
# abort if files exist
if((Test-Path($PfxFile)) -or (Test-Path($CerFile)))
{
Write-Warning "Failed, aspnet_dpapi already exists in $cwd"
Exit
}
$cert = New-SelfSignedCertificate `
-Subject $rootDomain `
-DnsName $rootDomain `
-FriendlyName "ASP.NET Data Protection $rootDomain" `
-NotBefore (Get-Date) `
-NotAfter (Get-Date).AddYears(10) `
-CertStoreLocation "cert:CurrentUser\My" `
-KeyAlgorithm RSA `
-Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" `
-KeyLength 2048 `
-KeyUsage KeyEncipherment, DataEncipherment
# -HashAlgorithm SHA256 `
# -Type Custom,DocumentEncryptionCert `
# -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1")
$store = 'Cert:\CurrentUser\My\' + ($cert.ThumbPrint)
$securePass = ConvertTo-SecureString -String $password -Force -AsPlainText
Export-Certificate -Cert $store -FilePath $CerFile
Export-PfxCertificate -Cert $store -FilePath $PfxFile -Password $securePass
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5441 次 |
| 最近记录: |