【问题标题】:NancyFX : Why is my IUserMapper singleton instantiated twice?NancyFX:为什么我的 IUserMapper 单例实例化了两次?
【发布时间】:2023-03-21 17:05:01
【问题描述】:

我正在尝试实现一个非常简单的 FormsAuthentication 示例。这不是现实生活,但它引发了一个问题。旨在成为应用程序级别单例的 AuthenticationService 似乎被实例化了两次。

代码如下:

public class User : IUserIdentity
{
    public string UserName { get; set; }
    public IEnumerable<string> Claims { get; set; }
}

public interface IAuthenticationService
{
    Guid GetIdentifier(string username, string password);
}

public class AuthenticationService : IUserMapper, IAuthenticationService
{
    public readonly Guid Identifier = Guid.NewGuid();
    private readonly string Username = "admin";
    private readonly string Password = "x";

    public Guid GetIdentifier(string username, string password)
    {
        return (username == Username && password == Password) ? Identifier : Guid.Empty;
    }

    public IUserIdentity GetUserFromIdentifier(Guid identifier, NancyContext context)
    {
        return (identifier == Identifier) ? new User { UserName = "admin" } : null;
    }
}

public class MyBootstrapper : DefaultNancyBootstrapper
{
    protected override void ConfigureApplicationContainer(TinyIoCContainer container)
    {
        base.ConfigureApplicationContainer(container);
        container.Register<IAuthenticationService, AuthenticationService>().AsSingleton();
    }
}

上面的代码被我的LoginModule 使用如下。请注意,我正在通过模块的构造函数注入 AuthenticationService 的应用程序级单例实例。

public LoginModule(IAuthenticationService authenticationService)
{
    Post["/login"] = _ =>
    {
        var identifier = authenticationService.GetIdentifier(
            (string) Form.Username, 
            (string) Form.Password);

        if (identifier.IsEmpty())
        {
            return Context.GetRedirect("~/login?error=true");
        }
        return this.LoginAndRedirect(identifier);
    };
}

应该发生的是当用户POSTs他们的用户名和密码时,这些是由AuthenticationService通过GetIdentifier(..)方法检查的。如果凭据匹配,则返回单个 GUID 标识符。这个GUID 将始终相同,因为它是作为readonly 字段创建的,因此在应用程序启动时首次实例化单例AuthenticationService 时设置一次。

然而事实并非如此。而是创建了两个不同的 AuthenticationService 实例,一个注入到 LoginModule 构造函数中并用于调用 GetIdentifier(..) 方法,另一个实例用于 Nancy 调用 IUserIdentity.GetUserFromIdentifier(..) 方法。

这两个实例有不同的GUID 标识符,因此GetUserFromIdentifier(..) 方法总是返回null。

我测试了一个没有实现IUserMapper 的标准单例服务,它按预期工作,只创建了一个实例。

因此,Nancy 似乎两次实例化 IUserMapper 单例,一次在 FormsAuthentication 期间供其内部使用,一次注入我的 LoginModule 构造函数!

你能看出我的错误吗?

谢谢

【问题讨论】:

    标签: singleton forms-authentication nancy


    【解决方案1】:

    这可能是因为您使用的是不同的接口,所以您有一个单例用于请求 IUsernameMapper 的事物,而另一个用于请求 IAuthenticationService 的事物。

    您可以:

    • 向您的身份验证服务实例注册两者
    • 拆分用户名映射器并在您的服务中依赖它(因此您的应用程序服务依赖于 IUsernameMapper - 这将与 Nancy 使用的相同)
    • 使用使用另一个接口解析的工厂注册其中一个(container.Register((c,p) => c.Resolve

    我问你为什么要这样做而不是仅仅使用内置的表单身份验证?

    【讨论】:

    • 我以为我 使用内置的表单身份验证 :-) 这不是这样做的方法吗?上面的示例旨在为我提供一个非常快速的单用户登录以保护单个管理页面(我没有数据存储,也不想为一个用户创建一个)。您能否指出我的解释,或者更好的是,请在此处提供一个快速代码示例。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 2014-08-23
    • 1970-01-01
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多