【问题标题】:.NET Identity Token invalid, machine key the same.NET Identity Token 无效,机器密钥相同
【发布时间】:2018-11-17 23:34:16
【问题描述】:

我在生成令牌以放入电子邮件以供用户重置密码时遇到问题。我在负载均衡器后面的两台 Web 服务器上的 IIS 7 上运行 .net 4.5 站点。

只要在生成它的同一台服务器上使用令牌,它就可以很好地工作。但如果另一台服务器是被击中的服务器,则“无效令牌”。产生错误。

我有三个可以测试的网址。负载平衡 url,以及直接指向负载平衡器后面的每个服务器的 url。我可以从负载平衡的 url 生成一个令牌并验证我点击了哪个服务器,然后我可以在同一服务器的直接 url 上使用该令牌。但是在对方服务器上使用它的组合不起作用。

最初我的机器密钥在两台机器上并不相同,我在一个多月前解决了这个问题。但它并没有解决问题。两台服务器都使用相同的代码库。负载平衡的域名令牌适用于直接进入其后面的服务器的域名,这意味着域名本身并不是我所知道的那样接近的因素。

我的配置还有什么问题?

【问题讨论】:

  • 没人有什么想法吗?这令人失望。

标签: asp.net


【解决方案1】:

事实证明,.net 身份系统默认情况下无法使用它的 UserTokenProvider 处理网络农场。到目前为止,我发现解决此问题的唯一方法是编写您自己的 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);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    • 2020-12-25
    • 2017-12-02
    • 2014-11-04
    相关资源
    最近更新 更多