1

FormsAuthenticationの非常に単純な例を実装しようとしています。それは現実の生活ではありませんが、問題を引き起こしました。アプリケーションレベルのシングルトンとなることを目的としたAuthenticationServiceは、2回インスタンス化されているように見えます。

コードは次のとおりです。

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識別子が返されます。これは、フィールドとして作成され、アプリケーションの起動時にシングルトンが最初にインスタンス化されるときに1回設定GUIDされるため、常に同じになります。readonlyAuthenticationService

ただし、そうではありません。代わりに、の2つの異なるインスタンスが作成されます。1つはコンストラクターにAuthenticationService挿入されてメソッドを呼び出すために使用され、もう1つはナンシーがメソッドを呼び出すために使用します。LoginModuleGetIdentifier(..)IUserIdentity.GetUserFromIdentifier(..)

これらの2つのインスタンスは異なるGUID識別子を持っているため、GetUserFromIdentifier(..)メソッドは常にnullを返します。

実装されていない標準のシングルトンサービスをテストしましたがIUserMapper、期待どおりに機能し、インスタンスは1つだけ作成されます。

したがって、ナンシーはIUserMapperシングルトンを2回インスタンス化しているようです。1回はFormsAuthentication中に内部で使用するため、もう1回はLoginModuleコンストラクターに注入するためです。

私の間違いを見つけられますか?

ありがとう

4

1 に答える 1

1

おそらく、別のインターフェイスを使用しているため、IUsernameMapper を要求するもの用に 1 つのシングルトンがあり、IAuthenticationService を要求するもの用に別のものがあるためです。

次のいずれかを実行できます。

  • 両方を認証サービスのインスタンスに登録します
  • ユーザー名マッパーを分割し、サービスでそれに依存します (したがって、アプリケーション サービスは IUsernameMapper に依存します - これはナンシーが使用しているものと同じになります)
  • 他のインターフェイスを使用して解決するファクトリを使用してそれらの1つを登録します(container.Register((c、p)=> c.Resolve)

組み込みのフォーム認証を使用するだけでなく、なぜこれを行っているのですか?

于 2012-06-13T11:20:17.327 に答える