[Delphi/ Access] database password versus user+password

Pagina: 1
Acties:
  • 116 views sinds 30-01-2008
  • Reageer

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 20-05 14:02

Tomatoman

Fulltime prutser

Topicstarter
Een Access-bestand kan worden beveiligd met een database password, dat Access vraagt zodra het bestand wordt geopend. In ADO is deze instelling toegankelijk via
Jet OLEDB:Database Password=algemeen wachtwoord
in de connection string.

Het is ook mogelijk om afzonderlijke gebruikersaccounts aan te maken. De accounts worden in ADO in de connection string ingesteld via
User ID=mijn naam;Password=mijn wachtwoord

Bij het maken van de databaseverbinding via een TADOConnection merk ik vanzelf of er een wachtwoord nodig is - als de verbinding niet kan worden opgebouwd is er blijkbaar een wachtwoord nodig :). Maar hoe weet ik van tevoren of dat het algemene wachtwoord is, de gebruikersnaam met persoonlijk wachtwoord, of beide?

Een goede grap mag vrienden kosten.


Verwijderd

Je zou naar de error-codes uit ADO kunnen kijken. Ik weet niet of ze verschillen afhankelijk van welk password nodig was. Ik heb het nu helaas niet voor je kunnen testen ;).

Wat ik altijd doe is een connection string in elkaar draaien met beide passwords; voor de ontbrekende passwords geef je dan blanco waardes mee.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 20-05 14:02

Tomatoman

Fulltime prutser

Topicstarter
De error code is in beide gevallen gelijk ($80040E4D), daar kom ik helaas niet verder mee. Het probleem is dat ik van tevoren niet weet welk wachtwoord is aangebracht. Inmiddels ben ik er wel achter dat Access zelf niet toestaat dat er een algemeen wachtwoord op een database wordt gezet als er ook gebruikersaccounts zijn, maar ik weet niet of dat alleen geldt voor het programma Microsoft Access of voor Access databases in het algemeen.

Een goede grap mag vrienden kosten.


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 20-05 14:02

Tomatoman

Fulltime prutser

Topicstarter
Inmiddels ben ik een stapje verder gekomen en heb ik alle mogelijke scenario's getest. Dit zijn mijn testresultaten:

Afbeeldingslocatie: http://img57.exs.cx/img57/3633/foutmeldingen.gif

De situatie met een user ID en bijbehorend wachtwoord wordt in sommige artikelen Jet security genoemd en in andere user-level security, maar het komt allemaal op hetzelfde neer. Bij de groene vakjes gaat inloggen probleemloos, bij de rode en oranje krijg ik de aangegeven foutmelding en bij de gele krijg ik een foutmelding omdat ik de desbetreffende database blijkbaar niet goed geconfigureerd heb (anders zou het inloggen goed gaan).

Hoe dan ook, aan de hand van de foutmeldingen kan ik nooit achterhalen of er een user-level wachtwoord of een database wachtwoord is ingesteld. Verder is de foutcode 80004005 een generieke foutcode die op allerlei problemen kan duiden. De error message kan ik niet gebruiken, omdat die taal- en versieafhankelijk is - leuk voor de gebruiker maar niet voor de programmeur.

Wie weet hoe ik in code kan onderscheiden met welk soort beveiliging een Access-bestand is beveiligd?

Een goede grap mag vrienden kosten.


  • Lustucru
  • Registratie: Januari 2004
  • Niet online

Lustucru

26 03 2016

Ado is een universeel verbindingsmechaniek, dus de errorcodes van ADO zeggen niet zoveel. 8004OE4D is algemeen 'authentification failded'en jij wilt weten waarom dat zo is. Je wilt dus de onderliggende foutcodes van de jet provider hebben. Die lees je uit via de errors colletion van de connectie. Een dbwachtwoordfout is ado 1905 / dao 3031; userpermissies is ado major 1907 / dao 3033.
Kijk hier eens naar. Is voor vb, maar eenvoudig om te zetten naar delphi mag ik aannemen.

[ Voor 65% gewijzigd door Lustucru op 03-10-2004 23:55 ]

De oever waar we niet zijn noemen wij de overkant / Die wordt dan deze kant zodra we daar zijn aangeland


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 20-05 14:02

Tomatoman

Fulltime prutser

Topicstarter
Dat lijkt te werken _/-\o_. Ik had er totaal niet bij stilgestaan dat er interessante informatie in de Errors collection van de connectie zou kunnen zitten. Het lukt me inderdaad om daar de foutcodes uit te filteren, precies volgens het artikel waar je naar verwijst. Bedankt!

Een goede grap mag vrienden kosten.


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 20-05 14:02

Tomatoman

Fulltime prutser

Topicstarter
Om het topic netjes af te sluiten zal ik de code posten waarmee ik nu herken wat voor soort beveiliging de Access-database kent.
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
uses
  Windows, SysUtils, Classes, Variants, ADODB, Math;

type
  { TJetError represents a Microsoft Jet database engine error }
  TJetError = record
    Major: Smallint;    // Major Jet error
    Minor: Smallint;    // Minor Jet error (or none)
    HasMinor: Boolean;  // Indicates if a minor Jet error is present
    DAOError: Word;     // Jet IDA Number (DAO error)
  end;

{ ExtractJetError interprets an ADO Error object a as TJetError,  }
function ExtractJetError(ADOError: Error): TJetError;

type
  TJetAuthenticationError = (jaeNone, jaeInvalidDBPassword,
    jaeInsuffUserPermissions);

{ If a TADOConnection's provider is Microsoft.Jet.OLEDB.4.0, the
  TADOConnection's Errors property contains Microsoft Jet database engine
  errors. JetAuthenticationError determines if any of these errors
  indicates an invalid database password (the password to open the 
  database file) or insufficient user permissions (including a bad
  username/password combination). }
function JetAuthenticationError(ADOErrors: Errors): TJetAuthenticationError;

implementation

function ExtractJetError(ADOError: Error): TJetError;
begin
  with Result do
  begin
    Major := LoWord(ADOError.NativeError) * Sign(ADOError.NativeError);
    Minor := HiWord(ADOError.NativeError) * Sign(ADOError.NativeError);
    HasMinor := Major <> Minor;
    DAOError := StrToIntDef(ADOError.SQLState, 0);
  end;
end;

function JetAuthenticationError(ADOErrors: Errors): TJetAuthenticationError;
const
  { translated from DBDAOERR.H: }
  E_DAO_InvalidPassword = 3031; // Not a valid password.
  E_DAO_AccessDenied = 3033;    // No permission for '|'.
var
  i: Integer;
  JetError: TJetError;
begin
  Result := jaeNone;
  for i := 0 to ADOErrors.Count -1 do
  begin
    JetError := ExtractJetError(ADOErrors[/norml][i][/]);
    case JetError.Major of
      1905: Result := jaeInvalidDBPassword;
      1907: Result := jaeInsuffUserPermissions;
    else
      case JetError.DAOError of
        E_DAO_InvalidPassword: Result := jaeInvalidDBPassword;
        E_DAO_AccessDenied: Result := jaeInsuffUserPermissions;
      end;
    end;
    if Result <> jaeNone then
      Break;
  end;
end;


Je kunt het ongeveer als volgt gebruiken:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  { Open the database. Prompt for user name and password if necessary. }
    LoginCompleteOrAborted := True;
    try
      ADOConnection.Connected := True;
    except
      on E: EOleException do
      begin
        if ADOConnection.Provider = 'Microsoft.Jet.OLEDB.4.0' then
          { Check if the error indicates a database password error or
            insufficient user permissions }
          case JetAuthenticationError(ADOConnection.Errors) of
            jaeNone: [geen wachtwoord nodig]
            jaeInvalidDBPassword: [database wachtwoord nodig]
            jaeInsuffUserPermissions: [username + wachtwoord nodig]
          end;

        case EOleException(E).ErrorCode of
          HRESULT($800A0E80): Abort; { Login procedure cancelled by user }
        else
          raise;
        end;
      end;
    else // try..except..else
      raise;
    end;

Een goede grap mag vrienden kosten.

Pagina: 1