Solved

Password protect an application and DB

Posted on 2004-08-26
7
1,195 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
ScreenConnect 6.0 Free Trial

Explore all the enhancements in one game-changing release, ScreenConnect 6.0, based on partner feedback. New features include a redesigned UI, app configurations and chat acknowledgement to improve customer engagement!

 
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

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

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…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
In a recent question (https://www.experts-exchange.com/questions/28997919/Pagination-in-Adobe-Acrobat.html) here at Experts Exchange, a member asked how to add page numbers to a PDF file using Adobe Acrobat XI Pro. This short video Micro Tutorial sh…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

772 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