在运行时更改web.config连接字符串的最佳方法是什么?

时间:2009-03-09 20:21:27

标签: asp.net database authentication web-applications

我对ASP.NET世界很陌生,所以我遇到了在运行时配置连接字符串的最佳方法并让整个应用程序使用该连接字符串时遇到一些麻烦。以下是我计划构建的应用程序的更多信息:

  • 应用程序使用表单身份验证,而不是Windows身份验证
  • 将有一个登录页面,用户提供其SQL Server登录ID和密码
  • 为简单起见,我希望所有SQLDataSource控件都指向web.config连接字符串。这将在设计时完成,而不是以编程方式设置它们。所以,他们会有这样的属性:  ConnectionString =“<%$ ConnectionStrings:MyDB%>”
  • 我想找到一种在运行时更改“MyDB”连接字符串的方法,以便它使用用户提供的登录ID和密码。但我不希望这个保存到web.config。它应仅对该用户的会话有效。

人们通常这样做的“标准”方式是什么?我假设一种方法是使用连接字符串创建一个Session变量,然后在页面加载期间以编程方式更改每个SQLDataSource控件的ConnectionString属性。但我希望尽可能避免这种情况。


由于许多人询问为什么我想为每个用户使用唯一的连接,并担心缺乏汇集,我想我会在这里评论,而不是评论每个单独的响应。

此应用程序的性质要求每个用户都使用自己的帐户连接到数据库。后端安全性与其用户帐户绑定,因此我们无法使用“用户”和“管理员”等通用帐户。我们还需要知道每个用户的特定身份以进行审计控制。该应用程序通常只有10到20个用户,因此缺乏池化不是问题。我们可以再次讨论这种方法的优点,但不幸的是我在这里没有选项 - 项目要求每个用户在他们自己的帐户下连接到数据库。

我很想要求Windows身份验证,但遗憾的是,此应用程序的某些实现需要SQL身份验证。

如果我可以在声明像这样的SQLDataSource控件时设置连接字符串,那么它将非常简单:

  <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
    ConnectionString = "<%= Session("MyConnectionString") %>"
    SelectCommand="SELECT * FROM [Customers]">
  </asp:SqlDataSource>

但我收到错误,因为它不喜欢&lt; %%&gt;标签那里。如果我在声明控件时无法执行此操作,那么对于应用程序中的每个SQLDataSource控件,以编程方式执行此操作的最简单方法是什么?

非常感谢大家的帮助!

9 个答案:

答案 0 :(得分:5)

如果您不想深入研究代码,可以采用另一种方法。

首先阅读expression builders上的这篇文章。我最喜欢的东西之一,我的网络应用程序!

现在有些代码:

首先在项目中创建一个包含以下内容的类:

using System;
using System.CodeDom;
using System.Web.UI;
using System.Web.Compilation;

namespace MyNamespace.Web.Compilation
{
    [ExpressionPrefix("code")]
    public class CodeExpressionBuilder : ExpressionBuilder
    {
        public override CodeExpression GetCodeExpression(BoundPropertyEntry entry,
           object parsedData, ExpressionBuilderContext context)
        {
            return new CodeSnippetExpression(entry.Expression);
        }
    }

}

然后,在web.config中注册表达式生成器,如下所示

...
<compilation debug="false">
  <expressionBuilders>
    <add expressionPrefix="Code" type="MyNamespace.Web.Compilation.CodeExpressionBuilder"/>
  </expressionBuilders>
</compilation>
...

(以上所有代码均来自here并稍有修改)

最后将您的SqlDataSource更改为以下(C#):

<asp:SqlDataSource ID="SqlDataSource1" runat="server" 
    ConnectionString='<%$ code: (string)Session["MyConnectionString"] ?? ConfigurationManageer.ConnectionStrings["myDefaultConn"].ConnectionString %>'
    SelectCommand="SELECT * FROM [Customers]">
</asp:SqlDataSource>

如果你想(并且我建议)创建一个静态类来处理连接字符串,你会说:

public static ConnectionManager
{
   public static string GetConnectionString()
   {
      return HttpContext.Current.Session["MyConnectionString"] as string ??
             ConfigurationManager.ConnectionStrings["DefaultConnectionStr"].ConnectionString;
   }
}

然后你的SqlDataSource将是

<asp:SqlDataSource ID="SqlDataSource1" runat="server" 
    ConnectionString='<%$ code: ConnectionManager.GetConnectionString() %>'
    SelectCommand="SELECT * FROM [Customers]">
</asp:SqlDataSource>

这样一来,如果您需要更改获取连接字符串的方式,就可以在一个地方完成!

答案 1 :(得分:1)

Web.config连接字符串加载到Session_Start中的会话变量。如果用户提供了他/她自己的凭据,请在会话变量中更新它们。否则,默认值(web.config值)将生效。

答案 2 :(得分:1)

我会说你有几个选择,一些与你拥有的东西一起工作,其他人会要求你改变一些东西。

  1. 将默认连接存储在web.config中,将其加载到会话中,使用它直到用户登录,然后在会话中更新该值。

  2. 实施Windows身份验证和身份模拟,并设置可以访问SQL Server框的Windows帐户。

  3. 如果您使用第一项,请创建一个将获得连接的共享帮助函数,首先检查会话,然后从web.config加载。这样,您的所有数据源仍然可以在设计时绑定。

    注意:这不是典型的情况,并且使用多个SQL Server帐户进行连接会产生性能影响,例如缺乏在其他项目中使用连接池的能力。

答案 3 :(得分:1)

我不建议你这样做,因为你会遇到可扩展性问题。 Web应用程序将无法使用连接池,并且将打开与用户访问它时一样多的连接。您将有许多真正的连接打开/关闭。

如果您决定继续:

  • 如果您可以使用Windows身份验证,请使用模拟+集成模式进行sql连接。使用Windows组在sql server上设置权限。
  • 您可以递归访问页面上的所有项目,查找sql​​datasources,并将连接应用于每个项目。您可以从global.asax附加到页面的oninit,以便将其应用于所有页面。

你为什么要这样做?涉及的约束是什么? (通常在Web应用程序上使用受信任的子系统模型,即在Web应用程序级别/或在单独的业务层进行身份验证/授权)

答案 4 :(得分:0)

如果不将其保存到web.config,则无法执行此操作。

答案 5 :(得分:0)

正如Mitch所说,如果用户使用不同的凭据登录,则会丢失连接池(如果这会导致不同的连接字符串。)

如果您只是担心将管理员用户与普通用户分开,只需要2个连接字符串,一个用于管理员,一个用于普通用户。使用asp.net role providers为用户提供适当的权限。

答案 6 :(得分:0)

我有类似的情况。我将连接字符串设置为web.config中的默认连接字符串。然后在代码后面,您可以将连接字符串设置为不同的值。在数据源选择事件触发之前,您必须在Page_Load中执行此操作,如此....

SqlDataSource1.ConnectionString = ConnectionString;

如果要确保未使用默认值,可以使默认值为非工作连接字符串并处理异常,或者只检查它是否为默认值,如果是,则抛出错误。您还可以检查用户是否在数据源的选择事件期间登录,如果没有,则取消该事件...

答案 7 :(得分:0)

您可以使用像Postsharp这样的方面编程库来在运行时动态更改连接字符串。

答案 8 :(得分:0)

我正在使用的方法(我忘记了我在哪里学习abbout)是在app启动时添加SettingsLoaded处理程序,然后在处理程序中设置新的连接字符串。我没有在ASP.NET中尝试这个,只是一个本地应用程序,所以你的里程可能会有所不同:

Settings.Default.SettingsLoaded += new System.Configuration.SettingsLoadedEventHandler(Default_SettingsLoaded);

void Default_SettingsLoaded(object sender, System.Configuration.SettingsLoadedEventArgs e)
{
    Settings.Default["ConnectionString"] = "my new connection string";
}