2

我正在使用 Oracle 用户来验证 .Net 应用程序的用户名和密码。现在我正在研究密码更改功能。数据库具有自定义密码验证,因此如果您尝试更改用户密码并提供无效密码,Oracle 会返回多个错误。

第一个错误总是“ORA-28003:指定密码的密码验证失败”,然后每次验证失败都会引发一个错误。当我尝试从 Toad 客户端更改用户密码时,这会正确显示。

但是,当我从我的应用程序执行此操作时,引发的 OracleException 仅返回第一个错误,因此我无法向用户显示他提供的新密码无效,这是应用程序的要求。那么我应该如何解决这个问题呢?

4

3 回答 3

1

为什么不将逻辑包装在存储过程中?它会调用 Oracle 密码验证函数,然后您根据需要解析结果,并将您想要的任何消息返回给 .net 客户端?

于 2013-04-09T22:11:35.637 回答
1

对于初学者,不要使用 OpenWithNewPassword 方法。它不仅知道各种版本的 ODP.net 和 DB 存在问题,而且当您只需要一个时,它会迫使您拥有两个不同的代码分支 - 如果用户的密码已经过期,IIRC 它就不起作用。

相反,基本逻辑是这样工作的:

  • 确保您可以使用用户的旧帐户和密码进行身份验证

  • 如果成功,请关闭该连接并打开一个单独的帐户,该帐户除了 exec privs 之外没有对 ChangePassword 存储过程的访问权限。

这是代码:

protected void BtnChangePassword_Click(object sender, EventArgs e)
{
  String connectionStringFormat = "Data Source={0};User Id={1};Password={2};pooling=false;";
  if (Page.IsValid)
  {
    Boolean hasHasError = false;
    String connectionString = String.Format(
      connectionStringFormat,
      IptDatabase.Text,
      IptUserName.Text,
      IptOldPassword.Text);
    OracleCommand cmd = new OracleCommand();
    using (cmd.Connection = new OracleConnection(connectionString))
    {
      try
      {
        cmd.Connection.Open();
      }
      catch (OracleException ex)
      {
        //allow to continue if the password is simply expired, otherwise just show the message
        if (ex.Number != 28001)
        {
          ShowErrorMessage(ex.Message);
          hasHasError = true;
        }
      }

      if (!hasHasError)
      {
        //successful authentication, open as password change account
        cmd.Connection.Close();
        cmd.Connection.ConnectionString = ConfigurationManager.ConnectionStrings[IptDatabase.Text].ConnectionString;
        cmd.Connection.Open();
        cmd.CommandText = "SysChangePassword";
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add("username", IptUserName.Text);
        cmd.Parameters.Add("newpassword", IptPassword.Text);
        try
        {
          cmd.ExecuteNonQuery();
          ShowInfoMessage("Password Changed");
        }
        catch (OracleException ex)
        {
          ShowErrorMessage(ex.Message);
        }


      }
    }
  }

在它最简单的形式中,proc 执行 'alter user 标识并类似于此处记录的用户:http: //www.adp-gmbh.ch/ora/plsql/change_password.html。但是 dbms_output 行对您没有多大好处,因此您可以抛出自定义异常:

create or replace procedure SysChangePassword(
  pUserName in varchar2, 
  pPassWord in Varchar2) as
begin
  -- Check for system users here and reject
  if upper(pUserName) in ('SYS','SYSTEM') then
            raise_application_error(-20012, 'not allowed');
  else
     execute immediate 'alter user '||pUserName||' identified by ' ||
           pPassWord;
  end if;
  exception --this isn't necessary if you'd rather examine and handle the specific exceptions on the .net side
     when others then
        raise_application_error(-20012, sqlerrm);
end;
/

拥有此过程的模式需要“更改任何用户”权限。为安全起见,您的应用程序应作为一个单独的用户连接,该用户仅在此 proc 上具有执行权限。相当

于 2013-04-11T20:50:58.577 回答
0

如果为 ASP.NET 编写代码,为什么不使用正则表达式验证器控件,如果编写桌面应用程序,为什么不使用 Regex.IsMatch(...) 函数?为什么你必须先去服务器才能得到生成的错误。你有强大的密码策略,你可以限制客户端的用户。

于 2013-04-10T14:47:51.833 回答