NancyFX:为什么我的IUserMapper单例实例化两次?

时间:2012-06-13 11:10:52

标签: singleton forms-authentication nancy

我正在尝试实现一个非常简单的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构造函数!

你能发现我的错误吗?

由于

1 个答案:

答案 0 :(得分:1)

这可能是因为你使用了不同的界面,所以你有一个单例用于请求IUsernameMapper的东西,另一个用于请求IAuthenticationService的东西。

你可以:

  • 同时注册您的身份验证服务实例
  • 拆分用户名映射器,并依赖于您的服务中的那个(因此您的应用程序服务依赖于IUsernameMapper - 这将与Nancy使用的相同)
  • 使用其他界面解析的工厂注册其中一个(container.Register((c,p)=&gt; c.Resolve

我问你为什么要这样做,而不是仅使用内置的表格auth?