4

オラクルのセキュリティを使用してユーザーを認証するSilverlightアプリケーションに取り組んでいます。(これはビジネス要件であるため、変更できません)。

これを行うには、提供されたユーザー名とパスワードを使用してデータベースへの接続を開こうとするWCFWebサービスを呼び出します。接続が失敗した場合、例外をキャッチしてユーザーにメッセージを返します。ログインコードは次のとおりです。

[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;
    }
}

パスワードの変更操作を実行した後も、ユーザーは古いパスワードで接続でき、新しいパスワードで接続できません。アプリケーションを再起動して初めて、変更が有効になっているようです。

オラクルのODP.netドライバーを使用しています。MicrosoftのOracleクライアントを使用すると、ユーザーはパスワードの変更後に新しいパスワードと古いパスワードの両方に接続できます。

パラメータは、preventCacheクライアントキャッシュのタイプがないことを確認するためだけにありました。クライアントから現在の日付を送信し、Webサービスから同じ値を返して、後続のリクエストで実際に変更されるかどうかを確認します。これは期待どおりに行われます。

接続のイベントをリッスンしてInfoMessage警告があるかどうかを確認しようとしましたが、これを行うと、パスワードの有効期限が切れた例外が発生するのを防ぎ、コードがに到達しませんeventHandler

私は完全に迷子になっています。この振る舞いは私には非常に奇妙に思えますが、問題の根本的な原因はまだわかりません。

デスクトップ(WPF)アプリケーションでメソッドLogInとメソッドをコピーしようとしましたが、まったく同じように動作します。ChangePasswordしたがって、問題はSilverlightクライアントにはないと思います。

4

1 に答える 1

1

わかりました、私はこれを理解しました。メソッドを実行した後でも接続が開かれたことをToadで確認しましたConnection.Close()。この動作は、Oracle の接続プーリング メカニズムの一部のようです。

接続文字列を含めるPooling=falseことで問題が解決しました。

于 2012-12-04T17:17:20.897 に答える