c# - 防止使用过期密码打开 ODP.net 连接

标签 c# .net wcf silverlight oracle

我正在开发一个使用 Oracle 安全性来验证用户身份的 Silverlight 应用程序。 (这是业务需求,因此无法更改)。

我通过调用 WCF Web 服务来实现此目的,该服务尝试使用提供的用户名和密码打开与数据库的连接。如果连接失败,我会捕获异常并向用户返回一条消息,这是登录代码:

[OperationContract]
public LoginResult LogIn(string username, string password, DateTime preventCache)
{
    var result = new List<string>();

    try
    {
       connectionString = ConfigurationManager.ConnectionStrings["SecurityBD"].ToString();
        connectionString = connectionString.Replace("[username]", username);
        connectionString = connectionString.Replace("[password]",passowrd)
        using (var connection = new Oracle.DataAccess.Client.OracleConnection())
        {


            connection.ConnectionString = connectionString;                    
            connection.Open();
            if (connection.State == System.Data.ConnectionState.Open)
            {                        
                connection.Close();
                return new LoginResult(true, GetPermisos(username), preventCache);
            }
            else
            {
                return new LoginResult(false, null, preventCache);
            }
        }

    }
    catch (Oracle.DataAccess.Client.OracleException ex)
    {
        if (ex.Number == 1017)
        {
            return new LoginResult(new SecurityError("Wrong credentials.", ErrorType.InvalidCredentials));
        }
        //Password expired.
        if (ex.Number == 28001)
        {
            return new LoginResult(new SecurityError("Password expired.", ErrorType.PasswordExpired));
        }
        //Acount is locked.
        if (ex.Number == 28000)
        {
            return new LoginResult(new SecurityError("Account is locked.", ErrorType.AccountLocked));
        }
        else
        {
            return new LoginResult(new SecurityError("An error occurred while attempting to connect." + Environment.NewLine + "Error: " + ex.ToString(), ErrorType.UndefinedError));
        }
    }
    catch (Exception exg)
    {
        return new LoginResult(new SecurityError("An error occurred while attempting to connect." + Environment.NewLine + "Error: " + exg.ToString(), ErrorType.UndefinedError));
    }
}

如果连接因密码过期而失败,我会向用户显示相应的消息,然后提示他输入旧密码和新密码,然后将新凭据发送到我的 Web 服务上的 ChangePassword 方法。

[OperationContract]      
public ChangePasswordResult ChangePassword(string username, string oldPasswrod, string newPassword)
{
    string connectionString = string.Empty;
    try
    {
                       connectionString = ConfigurationManager.ConnectionStrings["SecurityBD"].ToString();
        connectionString = connectionString.Replace("[username]", username);
        connectionString = connectionString.Replace("[password]",passowrd)
        using (var connection = new OracleConnection(connectionString))
        {                    
            connection.Open();
            if (connection.State == System.Data.ConnectionState.Open)
            {                        
                connection.Close();
                using (var newConnection = new Oracle.DataAccess.Client.OracleConnection(connectionString))
                {
                    newConnection.OpenWithNewPassword(Cryptography.TransportDecrypt(newPassword));
                    if (newConnection.State == System.Data.ConnectionState.Open)
                    {

                        return new ChangePasswordResult(null);
                    }
                }
            }
            return new ChangePasswordResult(new SecurityError("Couldn't connect to the database.", ErrorType.UndefinedError));
        }
    }
    catch (OracleException ex)
    {
        if (ex.Number == 1017)
        {
            return new ChangePasswordResult(new SecurityError("Wrong password", ErrorType.InvalidCredentials));
        }
        //Password expired.
        if (ex.Number == 28001)
        {
            using (var newConnection = new Oracle.DataAccess.Client.OracleConnection(connectionString))
            {
                try
                {
                    newConnection.OpenWithNewPassword(Cryptography.TransportDecrypt(newPassword));                            
                    if (newConnection.State == System.Data.ConnectionState.Open)
                    {
                        return new ChangePasswordResult(null);
                    }
                    else
                    {
                        return new ChangePasswordResult(new SecurityError("No se pudo establecer una conexión con la base de datos", ErrorType.UndefinedError));
                    }
                }
                catch (Oracle.DataAccess.Client.OracleException oex)
                {
                    if (oex.Number == 28003)
                        return new ChangePasswordResult(new SecurityError("You'r new password does not match the security requeriments.." + Environment.NewLine + oex.Message, ErrorType.PasswordNotChanged));
                    else
                        return new ChangePasswordResult(new SecurityError(oex.Message, ErrorType.UndefinedError));
                }
            }
        }
        //Acount is locked.
        if (ex.Number == 28000)
        {
            return new ChangePasswordResult(new SecurityError("Account is locked.", ErrorType.AccountLocked));
        }
        else
        {
            return new ChangePasswordResult(new SecurityError("Couldn't establish a connection." + Environment.NewLine + "Error: " + ex.Message, ErrorType.UndefinedError));
        }
    }
    catch
    {
        throw;
    }
}

在我执行修改密码操作后,用户仍然可以使用旧密码连接,而他无法使用新密码连接。只有在我重新启动应用程序后,更改才会生效。

我正在使用 oracle 的 ODP.net 驱动程序。使用微软的oracle客户端,修改密码后,用户可以使用新旧密码进行连接。

preventCache 参数仅用于验证不存在任何类型的客户端缓存。我从客户端发送当前日期,然后从 Web 服务返回相同的值,以查看它是否真的随着后续请求发生变化,它是否按预期进行。

我试过监听连接的InfoMessage事件,看是否有任何警告,但是这样做可以防止密码过期异常发生,并且代码永远不会到达事件处理程序

我完全迷失了,这种行为对我来说似乎很奇怪,我仍然没有找出问题的根本原因。

我尝试在桌面 (WPF) 应用程序上复制 LogInChangePassword 方法,它们的行为完全相同。所以我想问题不在 silverlight 客户端。

最佳答案

好的,我已经弄明白了。使用 Toad 检查连接提醒打开,即使在执行 Connection.Close() 方法后也是如此。这种行为似乎是 oracle 连接池机制的一部分。

在连接字符串中包含 Pooling=false 解决了这个问题。

关于c# - 防止使用过期密码打开 ODP.net 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13691030/

相关文章:

javascript - 如何减轻GPS追踪主页的压力

c# - Prolog C# 接口(interface)从文件中撤回

c# - 将大文件上传到 azure blob

.net - 如何使用强名称对 .NET 程序集 DLL 文件进行签名?

javascript - 从标签文本设置 Bootstrap Modal 中文本框的值

c# - 可以通过 C# 将类添加到对象的现有类属性吗?

c# - get_PropertyName()/set_PropertyName() 与 PropertyName?

c# - wcf 将枚举反序列化为字符串

.net - 我可以在 Windows 服务中托管 WCF 服务吗?

c# - 有人使用 WCF 客户端和 SSRS 网络服务吗?