2012-12-03 2 views
4

사용자를 인증하기 위해 oracle 보안을 사용하는 Silverlight 응용 프로그램을 작성하고 있습니다. (이것은 비즈니스 요구 사항이므로 변경할 수 없습니다).만료 된 암호로 ODP.net 연결이 열리지 않도록하십시오.

제공된 사용자 이름과 암호를 사용하여 데이터베이스에 대한 연결을 시도하는 WCF 웹 서비스를 호출하면됩니다. 연결이 실패하면, 나는 예외를 catch하고 사용자에게 메시지를 반환, 여기에 로그인 코드입니다 : 연결이 암호 만료로 인해 실패 할 경우

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

, 나는 사용자에게 다음 프롬프트에서 해당 메시지를 표시 새로운 패스워드를 입력 한 다음 웹 서비스의 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 매개 변수는 클라이언트 캐시 유형이 없음을 확인하기위한 것입니다. 클라이언트에서 현재 날짜를 보낸 다음 웹 서비스에서 동일한 값을 반환하여 후속 요청에서 실제로 변경되는지 확인하고 예상대로 수행하는지 확인합니다.

경고가 있는지 확인하기 위해 연결의 InfoMessage 이벤트를 청취하려고했지만 암호 만료 예외가 발생하지 않도록하고 코드는 eventHandler에 도달하지 않습니다.

나는 완전히 잃어 버렸습니다.이 행동은 저에게 이상한 것처럼 보입니다. 문제의 근본 원인을 아직 밝혀 내지 못했습니다.

데스크톱 (WPF) 응용 프로그램에서 LogInChangePassword 메서드를 tryied했는데 정확히 동일하게 동작합니다. 그래서 문제는 실버 라이트 클라이언트에 없다고 생각합니다.

답변

1

좋아, 알아 냈어. Toad로 확인하면 연결은 Connection.Close() 메소드를 실행 한 후에도 opend를 상기시킵니다. 이 동작은 Oracle의 연결 풀링 메커니즘의 일부인 것으로 보입니다.

Pooling=false을 연결 문자열에 포함하면 문제가 해결되었습니다.

관련 문제