【问题标题】:Change user password for Oracle database using sql statement in C#在 C# 中使用 sql 语句更改 Oracle 数据库的用户密码
【发布时间】:2019-01-10 21:50:08
【问题描述】:

我正在处理一个要求,我必须从我的应用程序中更改当前用户的 oracle 连接密码。

我发现我可以使用下面的语句来使用 SQL 来完成这个任务:

ALTER USER *username* IDENTIFIED BY *password*

但是,因为用户名和密码没有作为带引号的字符串发送到数据库,所以我不能使用绑定参数。 (这个答案也是stated

当我连接一个字符串并将其作为常规 sql 查询发送到我的 Entity Framework DbContext 实例时,我有一个可行的解决方案,如下所示:

using (var context = _dbContextFactory.CreateContext())
{
    await context.Database.ExecuteSqlCommandAsync(
      $"ALTER USER {username} IDENTIFIED BY \"{newPassword}\"");
}

这种方法的缺点是,通过在字符串中连接密码,我有 SQL 注入漏洞,并且用户不能在密码中使用某些保留字符,例如;和“

我不关心用户名参数,因为这是在后端代码中管理的,但是密码直接来自用户输入。

有什么方法可以使用安全的方法从 C# 更改 Oracle 数据库中的当前用户密码?我也对其他方法持开放态度,例如不同的方法或在数据库中创建存储过程,只要它可以在 C# 客户端应用程序中实现。

我们使用的是 Oracle 版本 12+,所以我不能使用 IDENTIFIED BY VALUES '' 语法

【问题讨论】:

  • 如何在 SQL Developer 中指定这些特殊字符?您在 Oracle 密码中可以使用哪些特殊字符?如果我没记错的话,密码要求非常严格,你根本不能使用"。验证用户输入足以防止 SQL 注入。
  • 您可以尝试在服务器上的存储过程中使用execute immediate 吗? adp-gmbh.ch/ora/plsql/change_password.html 然后你可以绑定到 proc 参数
  • @ThomasN 我们试图创建一个这样的过程,但是我们无法让它工作
  • 嘿,我试了一下,看起来你甚至不需要服务器端 proc。你可以声明一个BEGIN / END;直接在您的命令中。我已经添加了一个答案,虽然它在 ODP.net 中......不知道这是否会帮助你

标签: c# oracle


【解决方案1】:

对于username,我们必须提供Oracle 标识符(以防我们保留原始查询)

  • 最多 30 个字符
  • 必须以字母开头
  • 可以包括 $(美元符号)、_(下划线)和 #(井号)

我们可以通过正则表达式验证提供的值

if (!Regex.IsMatch(username, @"^[A-Za-z][A-Za-z0-9_#\$]{0,29}$")) {
  // username is invalid
}

对于password我们可以

  • 双引号:my"password -> my""password
  • 确保 password 仅包含有效字符(例如,让我们排除 unicode 控制字符,如退格和其他)

所以代码会是这样的

if (!Regex.IsMatch(username, @"^[A-Za-z][A-Za-z0-9_#\$]$")) {
  // username is invalid
}

if (string.IsNullOrEmpty(newPassword) || newPassword.Any(c => char.IsControl(c))) {
  // password is invalid
}

using (var context = _dbContextFactory.CreateContext()) {
  await context.Database.ExecuteSqlCommandAsync(
    $"ALTER USER {username} IDENTIFIED BY \"{newPassword.Replace("\"", "\"\"")}\"");
}

【讨论】:

【解决方案2】:

这似乎适用于我的本地 Oracle 测试数据库(来自 ODP.net 驱动程序)。重要的一点似乎是 BEGIN / END; (没有它就无法工作)。

using (var con = (OracleConnection)db.Server.GetConnection())
{
    con.Open();

    //string pw = "'''';++";
    string pw = "newpass";

    var cmd = new OracleCommand(@"
BEGIN
EXECUTE IMMEDIATE CONCAT('ALTER USER B identified by ',:pw);
END;", con);
    cmd.CommandType = CommandType.Text;

    var p2 = cmd.CreateParameter();
    p2.ParameterName = "pw";
    p2.Value = pw;
    p2.DbType = DbType.String;
    cmd.Parameters.Add(p2);

    cmd.ExecuteNonQuery();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-26
    相关资源
    最近更新 更多