我正在处理一项要求,必须从应用程序中更改当前用户的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注入漏洞,并且用户无法在密码中使用某些保留字符,例如;和“
我不关心username参数,因为它是在后端代码中管理的,但是密码直接来自用户输入。
是否可以使用安全方法从C#更改Oracle数据库中的当前用户密码?我也愿意接受其他方法,例如差异方法或在数据库中创建存储过程,只要它可以在C#客户端应用程序中实现即可。
我们正在使用Oracle 12+版本,因此我无法使用IDENTIFIED BY VALUES ''
语法
答案 0 :(得分:2)
对于username
,我们必须提供 Oracle标识符(如果我们保留原始查询)
我们可以通过正则表达式来验证提供的值:
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("\"", "\"\"")}\"");
}
答案 1 :(得分:0)
这似乎在我的本地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();
}