Ninject UOW模式,用户通过身份验证后的新ConnectionString

时间:2014-05-13 21:27:04

标签: c# entity-framework authentication connection-string repository-pattern

我想知道是否有人可以指出我正确的方向?

我正在使用UOW存储库模式,并通过Ninject注入我的依赖项。我有一个继承自NinjectModule的UnitOfWorkMapping类,我用它来将我的IUnitOfWork绑定到Dbcontext的具体实现,见下文

public class UnitOfWorkMapping : NinjectModule
{
    public override void Load()
    {
        Bind<IUnitOfWork>()
            .To<WebsiteDbContext>()
            .InRequestScope()
            .WithConstructorArgument(
                "connectionString",
                ConfigurationManager.ConnectionStrings[ConnectionStringKeys.UnauthorisedUser]
                    .ConnectionString);

        // Objects that explicitly need a DB context for the life of the request
        Bind<IUnitOfWorkInRequestScope>()
            .To<WebsiteDbContext>()
            .InRequestScope()
            .WithConstructorArgument(
                "connectionString",
                ConfigurationManager.ConnectionStrings[ConnectionStringKeys.UnauthorisedUser]
                    .ConnectionString);

        // Objects that specificall need a DB context for the life of the application
        Bind<IUnitOfWorkInApplicationScope>()
            .To<WebsiteDbContext>()
            .InSingletonScope()
            .WithConstructorArgument(
                "connectionString",
                ConfigurationManager.ConnectionStrings[ConnectionStringKeys.UnauthorisedUser]
                    .ConnectionString);
    }
}

因此,当应用程序启动时会调用它,并为我的站点用户提供未授权用户的上下文。此上下文具有数据库连接,该数据库连接连接到对数据库对象具有有限访问权限的数据库用户。

一旦用户登录到站点,我想切换到另一个连接,该连接将为具有对数据库对象的更广泛访问权限的数据库用户提供上下文访问权。

因此,当代码执行到达&#34; if(Request.IsAuthenticated)&#34;的真实条件块时。它已经在使用&#34;授权&#34;上下文的数据库连接。

    /// <summary>
    /// Handles the PostAuthenticateRequest event of the Application control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
    protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
    {
        String[] roles;
        var applicationConfiguration =
            (IApplicationConfiguration)
                DependencyResolver.Current.GetService(typeof(IApplicationConfiguration));
        var identity = HttpContext.Current.User.Identity;
        if (Request.IsAuthenticated)
        {
            var roleRepository =
                (IRoleRepository)DependencyResolver.Current.GetService(typeof(IRoleRepository));
            roles = roleRepository.GetRolesForUser(identity.Name);
        }
        else
        {
            roles = new[] { applicationConfiguration.UnknownUserRoleName };
        }
        var webIdentity = new WebIdentity(identity, roles);
        var principal = new WebsitePrincipal(webIdentity)
        {
            ApplicationConfiguration = applicationConfiguration
        };

        HttpContext.Current.User = principal;
    }

我还没有能够在网上找到一个足够接近我的代码来调整和实现的代码示例。请问任何人都可以提出建议吗?提前谢谢。

如果需要,可以提供指向完整代码的链接。

解决方案: 好的,所以在Erik的不懈帮助下,我们到了那里。我正在使用的解决方案就是这样..

public class UnitOfWorkMapping : NinjectModule
{
    public override void Load()
    {
        // Bind the IUnitOfWork for a user that is not logged in.
        Bind<IUnitOfWork>()
            .To<WebsiteDbContext>()
            .When(request => IsUserAuthenticated(request))
            .WithConstructorArgument(
                "connectionString", ConfigurationManager.ConnectionStrings[ConnectionStringKeys.MainUserConnectionString]
                    .ConnectionString);

        // Bind the IUnitOfWork for a user that is not logged in.
        Bind<IUnitOfWork>()
            .To<WebsiteDbContext>()
            .When(request => !IsUserAuthenticated(request))
            .WithConstructorArgument(
                "connectionString", ConfigurationManager.ConnectionStrings[ConnectionStringKeys.UnauthorisedUser]
                    .ConnectionString);

    }

    /// <summary>
    /// Determines if the user authenticated.
    /// </summary>
    /// <param name="request">The Ninject Activation request.</param>
    /// <returns>
    /// returns <c>true</c> if the user exists and is authenticated
    /// </returns>
    public Boolean IsUserAuthenticated(IRequest request)
    {
        return (
            (HttpContext.Current.User != null) &&
            HttpContext.Current.User.Identity.IsAuthenticated);
    }
}

我希望这可以帮助别人花费数天时间来解决这个问题。

1 个答案:

答案 0 :(得分:2)

如果您想对用户是否登录使用不同的绑定,则非常简单。

Bind<IUnitOfWork>()
   .To<WebsiteDbContext>()
   .When(x => !HttpContext.Current.Request.IsAuthenticated)
   .InRequestScope()
   .WithConstructorArgument(
       "connectionString",
        ConfigurationManager.ConnectionStrings[ConnectionStringKeys.UnauthorisedUser]
           .ConnectionString);

Bind<IUnitOfWork>()
    .To<WebsiteDbContext>()
    .When(x => HttpContext.Current.Request.IsAuthenticated)
    .InRequestScope()
    .WithConstructorArgument(
        "connectionString",
        ConfigurationManager.ConnectionStrings[ConnectionStringKeys.AuthorisedUser]
           .ConnectionString);

请注意,这两者都具有相同的IUnitOfWork绑定,它将根据用户是否登录返回正确的绑定。

我也会这样做:

Bind<IIdentity>()
    .To<WebIdentity>()
     ...

Bind<IIdentity>()
    .ToMethod(x => HttpContext.Current.User.Identity)
    .WhenInjectedInto(typeof(WebIdentity))
    ...

Bind<IPrincipal>()
    .To<WebsitePrincipal>()
    ...

然后,配置您的WebsitePrincipal的构造函数以获取IIdentity和IApplicationConfiguration参数,使WebIdentity的构造函数将IIdentity和IRoleRepository作为参数(注意.WhenInjectedInto使用现有的Identity)。让你的构造者完成工作。

然后你只需要写下面的内容(DI负责其余部分):

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
    HttpContext.Current.User = DependencyResolver.Current.GetService(typeof(IPrincipal));
}