2012-12-03 39 views
4

我正在使用Oracle安全性對用戶進行身份驗證的Silverlight應用程序。 (這是一項業務需求,因此無法更改)。防止使用過期密碼打開ODP.net連接

我這樣做是通過調用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驅動程序。使用Microsoft的oracle客戶端,用戶可以在密碼更改後連接新密碼和舊密碼。

preventCache參數僅用於驗證是否沒有客戶端緩存類型。我從客戶端發送當前日期,然後從Web服務返回相同的值,以查看它是否隨後續請求發生實際更改,並按預期發生。

我試着收聽InfoMessage事件的連接,看看是否有任何警告,但這樣做可以防止密碼過期異常上升,並且代碼永遠不會到達eventHandler

我完全失去了,這種行爲似乎很奇怪,我仍然沒有找到問題的根源。

我試着在桌面(WPF)應用程序上覆制LogInChangePassword方法,它的行爲完全一樣。所以我猜這個問題不在Silverlight客戶端中。

回答

1

好吧,我已經想通了。即使在執行Connection.Close()方法後,使用Toad檢查連接提醒opend。這種行爲似乎是來自oracle的連接池機制的一部分。

包括Pooling=false上的連接字符串解決了這個問題。