【问题标题】:How to implement a password change functionality with Oracle and a .Net client?如何使用 Oracle 和 .Net 客户端实现密码更改功能?
【发布时间】:2013-04-12 04:50:58
【问题描述】:

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

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

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

【问题讨论】:

    标签: c# .net oracle


    【解决方案1】:

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

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

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

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

    代码如下:

    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 identify by 并且与此处记录的类似: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 上具有执行权限。而是

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 这绝对是一种可能性,并且被考虑过。但问题是,当他的帐户过期时,需要允许用户更改他的密码。现在,它正在使用 oracle 连接中的 LoginWithDiffrentPassowrd() 方法,它允许这样做。但是为了使用存储过程来更改密码,用户应该登录,他不能。
      【解决方案3】:

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

      【讨论】:

      • 为什么 OP 应该重新发明轮子并在 C# 中重新实现工作策略?可能有其他应用程序连接到数据库 - 您将如何防止用户在这些应用程序中将密码更改为不安全的东西?
      • 首先,该数据库由来自不同公司的不同团队开发的许多系统访问,因此用户名和密码验证不应由应用程序控制。此外,客户端希望能够在闲暇时更改验证功能,而无需重写应用程序中的任何代码或配置文件。
      • 能否从 VS 以调试模式运行应用程序后得到的异常中粘贴堆栈跟踪?你没有得到 InnerException 属性吗?
      猜你喜欢
      • 2019-06-09
      • 1970-01-01
      • 1970-01-01
      • 2021-07-19
      • 1970-01-01
      • 2016-05-29
      • 1970-01-01
      • 1970-01-01
      • 2018-01-20
      相关资源
      最近更新 更多