我遇到了一个问题,我生成了令牌以放入电子邮件中,以便用户重设密码。我正在负载平衡器后面的两个Web服务器上的IIS 7上运行.net 4.5站点。
只要令牌在生成令牌的服务器上使用,令牌就可以很好地工作。但是,如果另一台服务器受到攻击,则为“无效令牌”。错误生成。
我有三个可以测试的网址。负载均衡的URL,并且直接指向负载均衡器后面的每个服务器的URL。我可以从负载平衡的URL生成令牌,并验证我命中的服务器,然后可以在同一服务器的直接URL上使用该令牌。但是在相反的服务器上使用它的组合都无效。
最初,我的机器密钥在两台计算机上都不相同,并且我在一个多月前解决了该问题。但这并没有解决问题。两台服务器都使用相同的代码库。而且,负载均衡域名令牌可以在直接通向其后方服务器的域名上工作,这意味着域名本身并不是我所能知道的。
我的配置还有什么问题?
答案 0 :(得分:0)
事实证明,默认情况下,.net身份系统无法使用其UserTokenProvider处理Web场。到目前为止,我发现此问题的唯一方法是编写自己的UserTokenProvider。幸运的是,事实证明这很容易做到,并且只需要很少的代码。
您可能已经有一个类似于以下内容的UserManager实现:
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager() : base(new UserStore<ApplicationUser>(new ApplicationDbContext()))
{
var provider = new DpapiDataProtectionProvider("MyApp");
this.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create(".Net Identity"));
}
}
将其更改为这样。
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager() : base(new UserStore<ApplicationUser>(new ApplicationDbContext()))
{
var provider = new MachineKeyProtectionProvider();
this.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create(".Net Identity"))
{
TokenLifespan = TimeSpan.FromHours(24)
};
}
}
然后创建缺少的类:
/// <summary>
/// Wrapper for the custom @MachineKeyDataProtector class
/// </summary>
public class MachineKeyProtectionProvider : IDataProtectionProvider
{
public IDataProtector Create(params string[] purposes)
{
return new MachineKeyDataProtector(purposes);
}
}
/// <summary>
/// Custom key provider because Microsoft's default provider does not support web farms
/// </summary>
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);
}
}