Solved

Password protect an application and DB

Posted on 2004-08-26
7
1,192 Views
Last Modified: 2010-04-05
Hi,

I want to put in a login prompt for my application.  The application uses an Access DB behind it, I want to password protect the DB as well so only a person who knows the passwords can use the application or go into the DB.  So from Delphi app the user will input the username and password for the access DB.

Can anyone offer me a solution here?  I am using ADO and setup a connection to the DB at application startup.  All other forms in the app use the ADO connection from the main form.

I want a simple form to be displayed with a username and password edit box as well as a login and cancel button.  I want to creat my own, not use the built in one as I want to include my logo on it.  

If Login is clicked and the login details are a match then the user gets in, if login details are incorrect then an error box is displayed and they are asked to re-enter the details.  After 3 failed attempts I want the app to close.

If the Cancel button is clicked the app closes cleanly.

Hope someone has a good solution out there for me, look forward to your replies.

I tried using the built in login prompt in the ADO connection but keep getting this error:

---------------------------
Debugger Exception Notification
---------------------------
Project BankManager.exe raised exception class EOleException with message 'Cannot start your application. The workgroup information file is missing or opened exclusively by another user'. Process stopped. Use Step or Run to continue.
---------------------------
OK   Help  
---------------------------

So if you could also let me know how to setup the Access DB with a username and password that would be create!

I know this is a big ask so if anyone can offer me a working solution I will give more points.....

Below is how I am setting up the connection to the DB from my main form...  Any questions just ask...

********************************************************************

function GetDBLOCATION : String;
var
  Reg : TRegistry;
begin
  Result := '';
  Reg := TRegistry.Create;
  try
    Reg.RootKey := HKEY_CURRENT_USER;
    if Reg.OpenKey ('\Software\'+application.title, true) then
      Result := Reg.ReadString ('DBNAME');
      Reg.CloseKey;
  finally
    Reg.Free;
  end;
end;

procedure TForm1.Startup(Sender: TObject);
var
  Reg : TRegistry;
  flag : Boolean;
begin
  flag := True;
  if Not DBConnected then
  begin
    DBPath := GetDBlocation;
    while not FileExists(DBPath) do
    begin
      OpenDialog1.Title := 'Database Location';
      OpenDialog1.Filter := 'Access Database|*.mdb';
      if OpenDialog1.Execute then
      begin
        Reg := TRegistry.Create;
        DBPath := OpenDialog1.FileName;
        try
          Reg.RootKey := HKEY_CURRENT_USER;
          Reg.OpenKey ('\Software\'+application.title, true); // Write path and address to register
          Reg.CloseKey;
        finally
          Reg.Free;
        end; // try
      end // if
      else
      begin
        showmessage('Unable to connect to the Database.');
        flag:=false;
        break;
      end;
    end;
    if flag then
      BankManagerConnection.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source='
                                + DBPath
                                + ';Persist Security Info=False';
    DBConnected := True;
  end;
end;

********************************************************************

Bego
0
Comment
Question by:begonz
  • 4
  • 2
7 Comments
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 11906419
in your DPR file put something like this:

    if TfrmLogin.Login = 0 then
      begin
        Application.Title := 'Applicant Tracker';
        Application.CreateForm(TfrmMain, frmMain);
        Application.Run;
      end
    else
      begin
        Exit;
      end

you main ADOConnection sits on the DataModule named DM and you try to open the connection with User and Pass you enter.
TfrmLogin implementation should look like this:

unit frLogin;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, frEntity, ExtCtrls, StdCtrls, Buttons, IniFiles;

type
  TfrmLogin = class(TfrmEntity)
    lblUsername: TLabel;
    edtUsername: TEdit;
    edtPassword: TEdit;
    lblPassword: TLabel;
    imgStop: TImage;
    lblLoginInfo: TLabel;
    btnLogin: TBitBtn;
    btnCancel: TBitBtn;
    btnOptions: TBitBtn;
    procedure btnLoginClick(Sender: TObject);
    procedure btnCancelClick(Sender: TObject);
  private
    DBParams  : String;
    procedure InitDBConnection;
  public
    ButtonClicked    : Integer;
    class function Login : Integer;
  end;

var
  frmLogin: TfrmLogin;

implementation

{$R *.dfm}

uses frLoginOptions
  , uConfiguration
  , frDataModule
  , uClientVars
  , frBusy
  ;

procedure TfrmLogin.btnLoginClick(Sender: TObject);
begin
  inherited;
  // try to login in the DB
  InitDBConnection;
  DM.DB.Params.Add('user_name=' + edtUsername.Text);
  DM.DB.Params.Add('password='  + edtPassword.Text);
  try
    TfrmBusy.OpenDB(DM.DB);
  except
    on E: Exception do
      begin
        // put back the params
        DM.DB.Params.CommaText := DBParams;
        // show the message
        MessageDlg(E.Message, mtError, [mbOK], 0);
        // Exit procedure
        Exit;
      end;
  end;
  ClientVar.UserName := edtUsername.Text;
  ButtonClicked := 0;
  ModalResult := mrOK;
end;

class function TfrmLogin.Login: Integer;
var
  frm_login     : TfrmLogin;
begin
  // show the login form
  Result := -1;
  frm_login := TfrmLogin.Create(nil);
  try
    frm_login.ShowModal;
  finally
    if Result = -1 then
      Result := frm_login.ButtonClicked;  
    frm_login.Free;
  end;
end;

procedure TfrmLogin.btnCancelClick(Sender: TObject);
begin
  inherited;
  ButtonClicked := 1;
  ModalResult := mrOK;
end;

procedure TfrmLogin.InitDBConnection;
var
  FName       : String;
  IniFile     : TIniFile;
  lc_str      : String;
  lc_int      : Integer;
  db_name     : String;
  db_server   : String;
begin
  FName := GetConfigFile(Application.ExeName);
  if not FileExists(FName) then
    begin
      MessageDlg('Configuration file missing!', mtError, [mbOK], 0);
      Exit;
    end;
  // open configuration file
  IniFile := TIniFile.Create(FName);
  try
    lc_int := IniFile.ReadInteger('DBConnection', 'ServerType', 0);
    if lc_int = 0 then
      begin
        // Local server
        db_name := IniFile.ReadString('DBConnection', 'Database', '');
        DM.DB.DatabaseName := db_name;
      end
    else
      begin
        // Remote server
        db_server := IniFile.ReadString('DBConnection', 'ServerAddr', '');
        db_name   := IniFile.ReadString('DBConnection', 'Database', '');
        lc_str    := IniFile.ReadString('DBConnection', 'Protocol', '');
        if UpperCase(lc_str) = 'TCP/IP' then
          begin
            // TCP/IP Connection
            // format -       <server_name>:<filename>
            DM.DB.DatabaseName := db_server + ':' + db_name;
          end
        else if UpperCase(lc_str) = 'NETBEUI' then
          begin
            // Named Pipe connection
            // format -       \\<server_name>\<filename>
            DM.DB.DatabaseName := '\\' + db_server + '\' + db_name;
          end
        else if UpperCase(lc_str) = 'SPX' then
          begin
            // SPX connection
            // format -       <server_name>@<filename>
            DM.DB.DatabaseName := db_server + '@' + db_name;
          end;
        // SQL Role
        lc_str := IniFile.ReadString('DBConnection', 'SQLRole', '');
        DM.DB.Params.Add('sql_role_name=' + lc_str);
        lc_str := IniFile.ReadString('DBConnection', 'CharSet', '');
        DM.DB.Params.Add('lc_ctype=' + lc_str);
        // copy the params in case of bad login
        DBParams := DM.DB.Params.CommaText;
      end;
  finally
    IniFile.Free;
  end;
end;

end.
0
 
LVL 5

Accepted Solution

by:
Voodooman earned 500 total points
ID: 11929767
Hi

It depends on the level of security that you are looking for.

I have been doing the following for several years and it has been very effective.

Setup a default password on your database.  Then hardcode the password into your executable (open a connection with the password).

Now your database is secure from casual opening with Access (users must have the password).

If you want users to Login - Within your database create a table with UserName and Password. A few simple forms in your App will allow you to create and remove users and passwords and verify Users and Passwords.

Before anyone screams at me that this is not very secure - in most cases we just want to hide the database from prying eyes and button clickers - ultimate security is not the issue.

Beware - you can buy Access Database password cracking tools on the Internet for $20 - how many users know (or care) to go to the trouble?

Voodooman
0
 

Author Comment

by:begonz
ID: 11957179
Thanks for your responses guys.  Ivanov, your solution seems complex, will take me a bit of time to go through it, still not sure how to setup the access DB though.

Voodooman, I like your idea, seems simple, hardcode the password and then have a table in the DB that contains the users own username and password.  Could you give me a bit more info on how I could do this?  Seems simpler than Ivanov's.  If I hard code the password, my connection string to the DB will be different I guess.

When the user puts in their user name and password, I guess it is just an SQL query to check that they both match.

I would like this app to be secure as it is a Banking tool and will contain the users bank details and transactions.  Needs to be password protected.  I know it isn't impossible to hack into anything but having a username and password set does make it a little harder.

Thanks.
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 5

Expert Comment

by:Voodooman
ID: 11958423
Hi

I dont use the Access DB with Delphi myself as I dont like ADO. (I use it with Visual Basic though).

Start off by opening the DB with no password - so that will give you the string for the connection.

Now open your Access DB with Access and create the password. Now add the required pwd=voodooman (or whatever).  Once you can open your password protected DB - you are half way there.

Now create a table called Passwords with Username and Password as the fields (create a unique index on the UserName is always a good idea).

In the show event of your main form call a modal form (F_Password.showmodal).

On the form put a box for the user name and another for the password (Perhaps TB_UserName and TB_Password)

Under the cancel put Application.Terminate

Under the Login Button put some code to verify the user name and password (Just query the database for the user name and password)

Something like

Try

mydataset.sql.clear;
mydataset.sql.add('Select * from Passwords were Username=' + QuotedStr(TB_User.Text) + 'Password=' + QuotedStr(Tb_Password.Text);

mydataset.active:=false;
mydataset.active:=true; //Open the recordset

If mydataset.recordcount>0 then self.close

Except

On E: Except do

//some error message here - I use my own routines called IMessage and EMessage

End;


This is easy and works well

Voodooman
0
 

Author Comment

by:begonz
ID: 11959821
Hi Voodooman.

I like you solution, makes sense, I think I can deal with the checking username and password thing fine but connecting to the DB is proving to be impossible.

I set a password as you said but when I try and build a test connection using ADO I keep getting the following error:

---------------------------
Microsoft Data Link Error
---------------------------
Test connection failed because of an error in initializing provider. Cannot start your application. The workgroup information file is missing or opened exclusively by another user.
---------------------------
OK  
---------------------------

Once I have this connection sorted I think I may be fine....

Help  :o(

Bego
0
 

Author Comment

by:begonz
ID: 11959825
PS:  Please see my original question to see how to make the DB connection.  Thanks.
0
 

Author Comment

by:begonz
ID: 12042240
Not quiet the full answer but thanks guys....I have posted another question re the connection to a password protected access DB...take a look here:

http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_21128519.html
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now