Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Login-Funktion: nur ein Benutzer mit bestimmten Zugangsdaten (https://www.delphipraxis.net/51859-login-funktion-nur-ein-benutzer-mit-bestimmten-zugangsdaten.html)

romber 20. Aug 2005 18:01


Login-Funktion: nur ein Benutzer mit bestimmten Zugangsdaten
 
Hallo!

Ich stehe vor einer ziemlich komplizierten Aufgabe und weiß nicht genau, ob so etwas überhaupt machbar ist und absturz- und pannensicher funktionieren kann. Und zwar, ich brauche eine Login/Logout-Funktion, die nur einen Benutzer mit den bestimmten Zugangsdaten zur selber Zeit rein lässt. Ich meine, wenn ein Benutzer angemeldet ist und ein zweiter versucht, sich mit den gleichen Zugangsdaten anzumelden, wird dem letzten den Zugang verweigert.

Auf ersten Blick ist das ganze gar nicht so schwer und lässt sich theoretisch mithilfe einer Datenbank realisieren. Man setzt den Status auf "1" wenn Benutzer angemeldet ist auf dann wieder auf "0" wenn Benutzer sich abmeldet. Voraussetzung ist natürlich, dass man das Programm immer richtig heruntergefahren wird. In Wirklichkeit ist die Sache wesentlich komplizierter. Denn niemand ist von einem Windowsabsturz und Strommausfall abgesichert und wenn etwas abstürzt, ist man natürlich nicht abgemeldet und kommt nicht noch mal rein etc. Da muss man wieder irgendwelche Pings einbauen, die wieder mal wahrscheinlich auf IP-Basis funktionieren und somit auch unsicher sind, weil die dynamisch zugewiesen IP-Adressen sich providerseitig ständig ändern... Habe jetzt mittlerweile selbst den Übersicht verloren, was da alles gemacht und berücksichtigt werden muss.

Letztens ist natürlich die Sicherheit des ganzen eine große Frage.

Hat jemand schon so etwas gemacht? Wie würdet Ihr so was realisieren und ob es Sinn macht, damit überhaupt anzufangen? Eure Meinungen und Erfahrungen sind mir jetzt wichtig.

Vielen Dank!

Jelly 20. Aug 2005 19:49

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Was für ein OS benutzt du. Steht vielleicht sogar irgendwo ein Windows2000 oder Windows2003 Domänenkontroller rum...

Ich weiss es nicht 100%, aber ich meine in den Gruppenrichtlinien kannst du so Sachen einstellen... Starte doch mal gpedit.msc und wühle dich durch. Das sollte auf XP Prof. zumindest realisierbar sein.

romber 20. Aug 2005 19:56

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Es läuft sogar Windows Server 2003 Enterprise auf dem Server-Rechner in der Firma, wo das ganze betrieben werden soll. Und eine Activ Directory einzurichten wäre auch kein Problem.

@Jelly: Meinst du jetzt, dass ich die selbst programmierte Anwendung irgendwie in den Domain Controller indegriere oder was? Habe ich nicht ganz vertanden?

Jelly 20. Aug 2005 20:02

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Ich würd mal kucken, ob das Ganze eben nicht direkt auf Domänencontroller im AD zu lösen ist. An so Sachen würd ich mich mit Delphi nicht rantrauen. Habt Ihr einen Administrator der in den ganzen AD Einstellungen fit ist, dann frag mal den. Ich bin mir fast sicher, dass es irgendwie dort direkt eine Möglichkeit gibt, die Anzahl der Sitzungen pro Benutzer auf eins zu beschränken.

romber 20. Aug 2005 20:27

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Was Windows angeht, bin ich mir auch ziemlich sicher, dass es so was gibt Die Frage ist, wie kann ich die Login-Funktion eigenes Programms mit der Benutzereinstellungen der Active Directory zusammenspielen lassen? :gruebel:

Phistev 20. Aug 2005 20:28

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Speicher statt '1' dir aktuelle Zeit in der Datenbank (am bestem als UNIX-Timestamp). Wenn der Login (oder die letzte Aktivität) länger als 3600 Sekunden (1 Stunde) zurückliegt, sollte das Programm abgestürzt sein. Damit brauchst du kein Active Directory

Palando 20. Aug 2005 20:47

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Du könntest wie Phistev sagte, einfach jede Aktivität überprüfen und wenn keine mehr da ist ausloggen.

Du könntest altlernativ auch einfach den Client alle X Sekunden eine Art "Keep alive"-Signal senden lassen und wenn das ne Zeit lang nicht kommt, ist das Programm tot. Das muss ja im Prinzip nicht oft sein... einmal alle 5 Minuten oder so...


Edit: Wobei ich Phistevs Methode eleganter finde, ehrlich gesagt.

Jelly 20. Aug 2005 20:53

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Zitat:

Zitat von romber
Was Windows angeht, bin ich mir auch ziemlich sicher, dass es so was gibt Die Frage ist, wie kann ich die Login-Funktion eigenes Programms mit der Benutzereinstellungen der Active Directory zusammenspielen lassen? :gruebel:

Ach so, ich dacht es ging um die Anmeldung in Windows überhaupt. Wenn es nur um dein eigenes Programm geht, musst du natürlich Hand anlegen. Da hab ich dich falsch verstanden.

Was für eine Datenbank nutzt du dann. Wenn du MSSQL einsetzen kannst, da kannst du dir mal die Tabelle sysprocesses aus der Master Datenbank anschauen, da siehst, welcher Login (loginame) gerade in der Datenbank eingeloggt ist. Du siehst sogar, aus welchem Programm (program_name) heraus er sich in der Datenbank eingeloggt hat. Du kannst ja jetzt bei deinem Programm prüfen, ob schon ein Eintrag für den besagten Login besteht. An die Zeit, wann die letzte Datenbankaktivität war kommst du auch über diese Systemtabellen vom SQL Server... Ich denke damit liesse sich was machen, zumal bei Systemabsturz diese Einträge vom SQL Server in regelmässigen Abständen aktualisiert werden.

romber 20. Aug 2005 21:40

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Zitat:

Zitat von Palando
Du könntest wie Phistev sagte, einfach jede Aktivität überprüfen und wenn keine mehr da ist ausloggen.

Du könntest altlernativ auch einfach den Client alle X Sekunden eine Art "Keep alive"-Signal senden lassen und wenn das ne Zeit lang nicht kommt, ist das Programm tot. Das muss ja im Prinzip nicht oft sein... einmal alle 5 Minuten oder so...


Edit: Wobei ich Phistevs Methode eleganter finde, ehrlich gesagt.

Wie sende ich so ein "Keep alive"-Signal? Über TCP-Sockets? Und wenn der Benutzer sich einloggt und dann ändert der Provider die IP-Adresse. Dann kommt Ping ja nie an, und der denkt Server, das Programm sei abgestürzt und loggt der Benutzer aus, obwohl der immer noch online ist. Ich denke, der Client muss sich auch irgendwie melden, a la "ich bin nicht tot" oder so etwas in der Art. Oder verstehe ich etwas falsch?

Phistev 20. Aug 2005 21:45

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Es war davon die Rede, dass der Client das Keep-Alive-Signal sendet, nicht der Server.
Dafür kann man TCP- oder UDP-Sockets verwenden

Mr_G 21. Aug 2005 07:44

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Ich habe da eine kleine Verständnisfrage:
Besitzt dein Programm Client und Server oder ist es ursprünglich nur eine Anwendug die von allen ausgeführt werden soll?
Wo (Firmennetzwerk/Internet) soll das denn stattfinden?

romber 21. Aug 2005 08:43

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Natürlich gibt es eine Serverteil und entsprechend ein Client.

SirThornberry 21. Aug 2005 09:06

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
die variante einfach einen Wert in die Datenbank zu schreiben das schon jemand eingeloggt ist find ich gar nicht so schlecht. Nur solltest du nicht dem zweiten Nutzer der sich einloggen will dies komplett verbieten sondern einen Hinweis ausgeben das bereits jemand eingeloggt ist und nachfragen ob das ignoriert werden soll. Du könntest ja auch alternativ noch in die Datenbank schreiben wann sich der erste nutzer angemeldet hat und dies im Hinweis mit anzeigen. Wenn dann im Hinweis so was steht wie "Es ist bereits ein Nutzer mit diesen Logindaten angemeldet (login: Vor einer Woche)" dann ist dem zweitanmelder eigentlich sofort klar das jemand das logout vergessen hat und somit kann er sich noch dafür entscheiden die meldung zu ignorieren.

Mr_G 21. Aug 2005 12:05

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Da es einen Client und einen Server gibt ist es denke ich wirklich eleganter die Benutzerverwaltung in das Programm zu intigrieren als extra ein ActiveDirectory aufzusetzen.

Zitat:

Zitat von SirThornberry
... Nur solltest du nicht dem zweiten Nutzer der sich einloggen will dies komplett verbieten sondern einen Hinweis ausgeben das bereits jemand eingeloggt ist und nachfragen ob das ignoriert werden soll. ...

Ich finde die Lösung mit einer "Ich lebe noch"-Nachricht des Clients etwas eleganter aber es kann sicher nicht schaden die An- und Abmeldungen zu Protkollieren und dem Benutzer zu sagen was Sache ist (z.B. wenn er sich schon eingeloggt hat).

Jelly 21. Aug 2005 12:41

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Hat überhaupt einer meinen Beitrag über die sysprocesses Tabelle beim MSSQL Server gelesen. Da läuft diese ganze "Ich bin da" Sache doch komplett im Hintergrund ab. Warum das Rad neu erfinden?

romber 21. Aug 2005 15:13

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Zitat:

Zitat von Jelly
Hat überhaupt einer meinen Beitrag über die sysprocesses Tabelle beim MSSQL Server gelesen. Da läuft diese ganze "Ich bin da" Sache doch komplett im Hintergrund ab. Warum das Rad neu erfinden?

Ja, aber um diese sysprocesses Tebelle einzusetzen, muss ich jede Instanz meines Programms mit MSSQL-Server verbinden oder wie? Das möchte ich nicht unbedingt haben.

Mr_G 21. Aug 2005 15:22

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Zitat:

Zitat von romber
Ja, aber um diese sysprocesses Tebelle einzusetzen, muss ich jede Instanz meines Programms mit MSSQL-Server verbinden oder wie? Das möchte ich nicht unbedingt haben.

Stimmt... Du müsstest jedes Mal zu der Datenbank Connecten.
Wenn du die Benutzer allerdings in deinem Programm verwalten würdest könnte man sich das ersparen in dem dein Server-Proggi die Benutzerdatenbank verwaltet. Somit müssten die Clients nur wie gewohnt zu deinem Server connecten.
Man könnte natürlich zu deinem Server connecten der dann wiederum zur MSSQL-DB connected aber naja ... :roll:

Jelly 21. Aug 2005 22:59

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Zitat:

Zitat von Mr_G
Wenn du die Benutzer allerdings in deinem Programm verwalten würdest könnte man sich das ersparen in dem dein Server-Proggi die Benutzerdatenbank verwaltet. Somit müssten die Clients nur wie gewohnt zu deinem Server connecten.

Und du denkst die selbstgebastelte Lösung läuft so stabil wie die im SQL Server integrierte :gruebel:

Ich bleib dabei... Wenn ein SQL Server zur Verfügung steht, dann würd ich den nutzen. Damit gehst du nämlich sämtlichen evntuell auftretenden Problemen aus dem Weg... Ich habs grad getestet. Mein Programm verbindet sich mit dem SQL Server, unter dem Windowsaccount. Dadruch taucht eine Zeile in der sysprocess Tabelle auf. Ich knall mein Programm über den Taskmanager ab. Und 1 Sekunde später verschwindet der Eintrag in der Tabelle. Also mal im Ernst. Was ist daran so problematisch. Wer natürlich lieber mit Sockets und Server und Clients rumspielt, bitte schön. Ich bin der Meinung das ist das Rad neu erfinden... Und geschweige denn, obs denn auch nachher wirklich schön rund wird.

romber 22. Aug 2005 15:47

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Zitat:

Zitat von Jelly
Und du denkst die selbstgebastelte Lösung läuft so stabil wie die im SQL Server integrierte :gruebel:

Ich bleib dabei... Wenn ein SQL Server zur Verfügung steht, dann würd ich den nutzen. Damit gehst du nämlich sämtlichen evntuell auftretenden Problemen aus dem Weg... Ich habs grad getestet. Mein Programm verbindet sich mit dem SQL Server, unter dem Windowsaccount. Dadruch taucht eine Zeile in der sysprocess Tabelle auf. Ich knall mein Programm über den Taskmanager ab. Und 1 Sekunde später verschwindet der Eintrag in der Tabelle. Also mal im Ernst. Was ist daran so problematisch. Wer natürlich lieber mit Sockets und Server und Clients rumspielt, bitte schön. Ich bin der Meinung das ist das Rad neu erfinden... Und geschweige denn, obs denn auch nachher wirklich schön rund wird.

OK, nehmen wir an, jede Instanz meines Programms stellt eine "stille", nur für Login-Zweck benutzte MSSQL-Verbindung her. Tatsächlich wird einen neuen Datensatz in der Tabelle sysprocesses erstellt, doch wie kann ich den Inhalt der Spalten für meinen Zweck benutzen? Den Datensatz wird doch einfach so erstellt, sobald eine Anwendung mit dem MSSQL Server verbindet. Habe versuch, ein Paar neuen Spalten in der Tabelle zu erstellen um dann damit etwas anzufangen, doch das ging nicht.

Jelly 22. Aug 2005 16:14

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von romber
doch wie kann ich den Inhalt der Spalten für meinen Zweck benutzen?

Die Spalten, die dich interessieren werden, sind:
  • hostname
  • program_name
  • nt_username
  • loginame
Bei program_name möchte ich noch bemerken, dass da nur was erscheint, wenn du in den Projektoptionen deines Delphi Programms die Versionsinfo mit reinkompilierst, und unten in der Liste einen Wert für Produktname setzt.

loginame ist der Login, mit dem du dich in der Datenbank einloggst. Vorausgesetzt, du nutzt die Windowsauthentifizierung beim SQL Server... Da steht dann sowas wie computername\windowslogin

Mit diesen beiden Spalten hast du doch sämtlich Informationen, die du brauchst. Um deinen Windowslogin im Delphi rauszufinden, kannst du mal die Forensuche bemühen, da sollte sich was finden lassen, ansonsten, kuck dir die beigelegte Komponente mal an. Beim Programmstart verbindest du dich mit dem SQL Server, in eine x-beliebige Datenbank. Sollte nach Möglichkeit eben nicht die Master Datenbank sein. In deiner Datenbank erstellst du eine View
SQL-Code:
create view vwLogins as
select hostname, program_name, nt_username, loginame from master.dbo.sysprocesses
where program_name='Dein Programmname'
wobei 'Dein Programmname' dem Produktnamen in den Delphi Projektoptionen entsprechen muss. Diese View muss also nicht in der Master Tabelle erzeugt werden. Auf diese View gibst du lediglich Lesezugriff für all deine Benutzer im Netz.

Zitat:

Zitat von romber
Den Datensatz wird doch einfach so erstellt, sobald eine Anwendung mit dem MSSQL Server verbindet.

Korrekt... Und um jetzt zu prüfen, ob die Anwendung schon sonstwo läuft, zählst du einfach die Records aus deiner View, die deinem nt_username entsprechen. Ist die Anzahl 1, so bist du der erste. Ist sie grösser eins, so läuft die Anwendung bereits.


Zitat:

Zitat von romber
Habe versuch, ein Paar neuen Spalten in der Tabelle zu erstellen um dann damit etwas anzufangen, doch das ging nicht.

:warn: Böser Fehler... sysprocesses ist eine Systemtabell vom SQL Server, und da fummelt man nicht dran rum. Würd mich wundern, wenn du da überhaupt was ändern darfst.

Also nochmal zusammengefasst... Lege dir eine Datenbank an, erstelle die besagte View, und vergib die Recht an deine Domain User im SQL Server auf diese View. Bei deinem Programmstart verbindest du dich einfach mit der Datenbank. Wenn alles korrekt konfiguriert ist, brauchst du dazu kein Login und Passwort, da der Windowsaccount dafür benutzt wird. Fehlt das schon fehl, weil du diesem Windowsaccount nicht erlaubst, in die DB einzuloggen, kannst du ja schon gleich den Programmstart verweigern. Ansonsten zählst du die Records in der View die deinem nt_usernam entsprechen, also etwa

SQL-Code:
select count(*) as N from vwLogins where nt_username='DeinWindowsLogin'
Ist N=1, so darfst du das Programm starten. Ist N > 1, halt nicht.

neolithos 22. Aug 2005 16:23

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Zitat:

Zitat von Jelly
Hat überhaupt einer meinen Beitrag über die sysprocesses Tabelle beim MSSQL Server gelesen. Da läuft diese ganze "Ich bin da" Sache doch komplett im Hintergrund ab. Warum das Rad neu erfinden?

Ich schon, und ich habe sowas mit einem ASA-Server (ist ähnlich dem MSSQL) schon gemacht, es lief auf einen einzigen SQL-Befehl raus. Kann man also nur empfehlen.

romber 22. Aug 2005 19:47

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
@Jelly: Erstmal vielen Dank für deine Mühe! :hi: An allen anderen auch vielen Dank!

Im Bezug auf deinen letzten Beitrag: zurzeit läuft den MS SQL Server im SQL Auth.-Modus. Muss ich unbedingt dieses auf Windows-Authenifizierung ändern? Wenn ich das doch ändere, muss ich für jeden Benutzer meines Programms (alle sind ausschließich außerhalb der Domain und der Arbeitsgruppe) ein Windows-Konto erstellen?

Mr_G 22. Aug 2005 20:04

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Zitat:

Zitat von Jelly
Zitat:

Zitat von Mr_G
Wenn du die Benutzer allerdings in deinem Programm verwalten würdest könnte man sich das ersparen in dem dein Server-Proggi die Benutzerdatenbank verwaltet. Somit müssten die Clients nur wie gewohnt zu deinem Server connecten.

Und du denkst die selbstgebastelte Lösung läuft so stabil wie die im SQL Server integrierte :gruebel:

Wieso nicht? Wenn man das ordentlich macht sollte das doch ohne größere Probleme gehen, oder?

Zitat:

Zitat von Jelly
Ich bleib dabei... Wenn ein SQL Server zur Verfügung steht, dann würd ich den nutzen. Damit gehst du nämlich sämtlichen evntuell auftretenden Problemen aus dem Weg... Ich habs grad getestet. Mein Programm verbindet sich mit dem SQL Server, unter dem Windowsaccount. Dadruch taucht eine Zeile in der sysprocess Tabelle auf. Ich knall mein Programm über den Taskmanager ab. Und 1 Sekunde später verschwindet der Eintrag in der Tabelle. Also mal im Ernst. Was ist daran so problematisch. Wer natürlich lieber mit Sockets und Server und Clients rumspielt, bitte schön. Ich bin der Meinung das ist das Rad neu erfinden... Und geschweige denn, obs denn auch nachher wirklich schön rund wird.

Ich persönlich würde das nach deinem Tipp (den ich natürlich gelesen hab) auch so machen, falls mir ein MSSQL-Server zur Verfügung steht. Nur führen (wie immer) viele Wege zum Ziel und romber schien ja einen anderen Weg einschlagen zu wollen ;)

Jelly 22. Aug 2005 20:05

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Zitat:

Zitat von romber
Im Bezug auf deinen letzten Beitrag: zurzeit läuft den MS SQL Server im SQL Auth.-Modus. Muss ich unbedingt dieses auf Windows-Authenifizierung ändern? Wenn ich das doch ändere, muss ich für jeden Benutzer meines Programms (alle sind ausschließich außerhalb der Domain und der Arbeitsgruppe) ein Windows-Konto erstellen?

Wenn du die Standardeinstellung vom SQL Server hast, so läuft ins beiden Modi, als SQL und Windowsauthentifizierung. Die Windowsauthentifizierung ist nicht rein auf die Domäne bezogen... Du kannst die Logins auch einfach über den Computernamen definieren, also etwa MEINPC\AccountName.

Ach ja, hier noch der benötigte ConnectionString wenn du über ADO gehst...
Code:
ConnectionString := format (
       'Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=%s;Data Source=%s',
       [DatabaseName,
        ServerName]) ;

romber 22. Aug 2005 21:46

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
OK, ich glaube, Jellys Lösung ist in meinem Fall ideal.
Ein kleines Problemchen habe ich aber noch: stellen wir vor, die Anwendung hat die Verbindung mit der MSSQL-Datenbank, dann ändert Provider plötzlich die IP-Adresse. Verbindung wird abgebrochen, Anwendung läuft jedoch weiter. In der sysprocesses wird der entsprechende Datensatz sofort gelöscht. Das heisst, anderer User kann sich schon problemlos einlogen. Oder noch schlimmer: den Datensatz bleibt für "immer" da. Und das alles kann öffters vorkommen, weil die Provider heutzutage ändern die IP-Adressen ständig. Gibt es was dagegen?

jensw_2000 23. Aug 2005 00:28

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Zitat:

OK, ich glaube, Jellys Lösung ist in meinem Fall ideal.
Ein kleines Problemchen habe ich aber noch: stellen wir vor, die Anwendung hat die Verbindung mit der MSSQL-Datenbank, dann ändert Provider plötzlich die IP-Adresse. Verbindung wird abgebrochen, Anwendung läuft jedoch weiter. In der sysprocesses wird der entsprechende Datensatz sofort gelöscht. Das heisst, anderer User kann sich schon problemlos einlogen. Und das alles kann öffters vorkommen, weil die Provider heutzutage ändern die IP-Adressen ständig. Gibt es was dagegen?
In diesem Fall musst du imho den "einfachen und sicheren Weg" verlassen und selbst was bauen.
Ich habe dir dazu mal schnell was ausgearbeitet.

Erstelle dir aber bitte eine eigene Datenbank, bitte keine Experimente mit der "Master-DB"

Hier mal der grobe Ablauf:

1. Du brauchst eine DB

> Enterprise Manager > Neue Datenbank > Name "LoginTest"

2. Du brauchst eine Tabelle in der Benutzer und Workstations gespeichert werden

SQL-Code:
USE LoginTest
GO
CREATE TABLE [SYS_ActiveUsers]
(
  [USERNAME] varchar(50) NOT NULL,                   -- Spalte für den Benutzernamen
  [Workstation] varchar(12) NOT NULL,                -- Spalte für den Netbiosnamen der Workstarion
  [LAST_SEEN] datetime DEFAULT (getdate()) NOT NULL, -- Spalte für das letzte Login/KeepAlive eines Users
  [LOCK_TIME_SECS] int DEFAULT (600) NOT NULL        -- (bedingte) Verfallszeit in Sekunden
)
ON [PRIMARY]
GO
3. Du brauchst eine SP, die beim Anmelden jedes einzelnen Users aufgerufen wird.
Dieser SP übergibst du den aktuellen Benutzernamen und den aktuellen PC-Namen.
Sie gibt dir ein BIT (AllowLogin) zurück, das du in deiner Software auswerten kannst.
Zudem gibt es ein BIT (Logout) mit dem du einen User regulär ausloggen kannst.

SQL-Code:
Use LoginTest
GO
CREATE PROCEDURE SYS_Check_Single_Login
(
 @USERNAME VARCHAR(50) = NULL,
 @WORKSTATION VARCHAR(12) = NULL,
 @LOGOUT BIT = NULL,
 @AllowLogin BIT = 0 OUTPUT
)
AS
BEGIN

-- Variablen deklarieren

DECLARE @TEMPTIME DATETIME
DECLARE @TEMPDIFF INTEGER

-- Parameter überprüfen

IF @USERNAME IS NULL OR @WORKSTATION IS NULL
BEGIN
  SET @AllowLogin = 0
  RAISERROR('Benutzername und Arbeitsstationsname müssen übermittelt werden',16,1,'SQL-Login')
END

-- Logout ??

IF @LOGOUT IS NULL SET @LOGOUT =0

IF @LOGOUT = 1
BEGIN
  -- Benutzer meldet sich regulär ab
  DELETE FROM SYS_ActiveUsers
        WHERE USERNAME=@USERNAME
          AND WORKSTATION=@WORKSTATION -- ggf. weglassen, damit das ganze Geraffel nicht zu starr wird ..
  SET @AllowLogin=0
END
ELSE BEGIN


  IF EXISTS (
             SELECT USERNAME
             FROM SYS_ActiveUsers
             WHERE USERNAME=@USERNAME AND WORKSTATION = @WORKSTATION
            )
  BEGIN
    -- Relogin (selber User von der selben Workstation)
    -- Last_Seen Updaten und AllowLogin setzen
    UPDATE SYS_ActiveUsers SET LAST_SEEN = GETDATE() WHERE USERNAME=@USERNAME
    SET @AllowLogin=1
  END
  ELSE BEGIN

    IF EXISTS (
               SELECT USERNAME
               FROM SYS_ActiveUsers
               WHERE USERNAME=@USERNAME AND WORKSTATION <> @WORKSTATION
              )
    BEGIN
      -- Login des selben Users von einer anderen Workstation)
      -- "Verfallsdatum" prüfen, ggf. Last_Seen Updaten und AllowLogin setzen

      SELECT @TEMPTIME = LAST_SEEN,
             @TEMPDIFF = LOCK_TIME_SECS
       FROM SYS_ActiveUsers
       WHERE USERNAME=@USERNAME AND WORKSTATION <> @WORKSTATION
   
      IF ABS( DATEDIFF( SECOND,@TEMPTIME,GETDATE() ) ) > @TEMPDIFF
      BEGIN
        -- Das "Verfallsdatum" des letzten Logins ist abgelaufen
        -- Tabelle SYS_ActiveLogins um den verwaisten User bereinigen
        DELETE FROM SYS_ActiveUsers WHERE USERNAME=@USERNAME
        -- Eigenen USERNAME und Workstation in SYS_ActiveUsers eintragen
        INSERT INTO SYS_ActiveUsers (USERNAME  
                                    ,WORKSTATION
                                    ,LAST_SEEN
                                    ,LOCK_TIME_SECS)
                        VALUES     (@USERNAME
                                    ,@WORKSTATION
                                    ,GETDATE()
                                    ,600) -- Timeout Sekunden (Verfallszeit)  
        SET @AllowLogin=1 
      END
      ELSE BEGIN
        -- Das "Verfallsdatum" des letzten Logins ist nicht nicht überschritten
        -- Login verweigern
        SET @AllowLogin=0
      END
    END
    ELSE BEGIN
      -- USERNAME steht noch nicht in der Tabelle SYS_ActiveUsers
      -- Hinzufügen ...
      INSERT INTO SYS_ActiveUsers (USERNAME
                                  ,WORKSTATION
                                  ,LAST_SEEN
                                  ,LOCK_TIME_SECS)
                      VALUES     (@USERNAME
                                  ,@WORKSTATION
                                  ,GETDATE()
                                  ,600) -- Timeout Sekunden (Verfallszeit)
      SET @AllowLogin=1
    END
  END

END

END

Diese SP rufst du beim Annmelden eines Users auf, und sie gibt dir, wie gesagt, ein Bit zurück, mit dem du prüfen kannst, ob sich der User anmelden darf.

Zum Ausloggen ruft du die selbe SP noch einmal auf, jedoch mit dem Parameter Logout = 1

Um das KeepAlive eines Users zu setzen, ruft du die SP alle 5-8 Minuten mal wieder auf ...


Für die Delphi würde ich mir an deiner Stelle eine kleine Function basteln:


Delphi-Quellcode:
var
  isAuthentificated:Boolean;

function CheckLogin(Logout:Boolean): Boolean;
  var SP:TAdoStoredProc;
begin

SQL - Syntax Hinweis
--------------------------------------------
CREATE PROCEDURE SYS_Check_Single_Login
(
 @USERNAME VARCHAR(50) = NULL,
 @WORKSTATION VARCHAR(12) = NULL,
 @LOGOUT BIT = NULL,
 @AllowLogin BIT = 0 OUTPUT
)
}

  SP:=TAdoStoredProc.create(self);
  SP.Connection:=MeineAdoConn; // Hier deine AdoConn
  try
    SP.Procedurename:='SYS_Check_Single_Login';
    SP.Parameters.refresh;
    SP.Parameters[1].Value:=MeinUserName;
    SP.Parameters[2].Value:=MeinPcName;
    if Logout then SP.Parameters[3].Value:=1
      else SP.Parameters[3].Value:=0;
    SP.ExecProc;
    Result:=SP.Parameters[4].Value;
  finally
    FreeAndNil(SP);
  end;

  if Authentificated AND (NOT Logout) AND (NOT Result) then
  begin
    Showmessage('Ihr login wirde gelöscht, weil von Ihrer Arbeitsstation keine "KeepAlive-Aufrufe"'+#13#10+
                'an die SP "SYS_Check_Single_Login" gesendet wurden, bzw. deren Timing nicht passt ...');
  end;

  if (NOT Authentificated) AND (NOT Result) then
  begin
    Showmessage('Ein anderer Benutzer ist im Moment als "'+MeinUsername+'" angemeldet.'+#13#10+
                'Bitte verwenden Sie einen anderen Benutzernamen oder versuchen Sie es später noch einmal.');
  end;
 
  isAuthentificated:=(NOT Logout) AND RESULT;

end;

Hoffentlich ist das eine Lösung, die deinen Anforderungen annähernd entspricht ...

Schöne Grüße,
Jens

:hi:

(bearbeitet - ein paar Kleinigkeiten korrigiert ...)

Jelly 23. Aug 2005 07:59

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Zitat:

Zitat von romber
stellen wir vor, die Anwendung hat die Verbindung mit der MSSQL-Datenbank, dann ändert Provider plötzlich die IP-Adresse. Verbindung wird abgebrochen, Anwendung läuft jedoch weiter.

Nun, gegen diesen Missstand wirst du nicht viel machen können. Wenn die Verbindung weg ist, so besteht natürlich auch keine Verbindung mehr zur Datenbank. Da hilft dann wirklich nur noch noch selbstgezimmerte Lösung, wie die perfekt von Jens dargelegt wurde.

romber 23. Aug 2005 14:52

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
@jensw_2000
im Bezug auf deinen letzten Beitrag: ich kann nicht ganz nachvollziehen, wann wird dieses Abschnitt de Code

Delphi-Quellcode:
if Authentificated AND (NOT Logout) AND (NOT Result) then
  begin
    Showmessage('Ihr login wirde gelöscht, weil von Ihrer Arbeitsstation keine "KeepAlive-Aufrufe"'+#13#10+ 
                'an die SP "SYS_Check_Single_Login" gesendet wurden, bzw. deren Timing nicht passt ...');
  end;
ausgeführt wird :shock:

Und hier ist noch ein Problem mit Logout. Ich übergebe Logout = 1 und anstatt den Datensatzt aus der Tabelle zu löschne, wird LAST_SEEN einfach aktualisiert. Da ist wohl noch ein kleines Fehler irgendwo in der SP.

jensw_2000 23. Aug 2005 15:23

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Zitat:

Und hier ist noch ein Problem mit Logout. Ich übergebe Logout = 1 und anstatt den Datensatzt aus der Tabelle zu löschne, wird LAST_SEEN einfach aktualisiert. Da ist wohl noch ein kleines Fehler irgendwo in der SP.
Du hast recht.
Ich habe den SP Code (von oben) mal korrigiert anstatt ihn noch einmal komplett korrigiert zu posten, damit der Thread überschaubar bleibt ..


Zitat:

im Bezug auf deinen letzten Beitrag: ich kann nicht ganz nachvollziehen, wann wird dieses Abschnitt de Code

Quellcode: markieren
if Authentificated AND (NOT Logout) AND (NOT Result) then
begin
Showmessage('Ihr login wirde gelöscht, weil von Ihrer Arbeitsstation keine "KeepAlive-Aufrufe"'+#13#10+
'an die SP "SYS_Check_Single_Login" gesendet wurden, bzw. deren Timing nicht passt ...');
end;



ausgeführt wird
Eigentlich nie :roll: :oops:

Naja,

Dafür, das der Code zum Großteil im Beitragseditor entstanden ist, was nicht ganz shlecht ... :zwinker:



Schöne Grüße,
Jens
:hi:

romber 23. Aug 2005 15:26

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Zitat:

Zitat von jensw_2000
...Dafür, das der Code zum Großteil im Beitragseditor entstanden ist, was nicht ganz shlecht ... :zwinker:

War sogar sehr-sehr gut :P :thumb: Probiere gleich aus.

jensw_2000 9. Jul 2006 23:08

Re: Login-Funktion: nur ein Benutzer mit bestimmten Zugangsd
 
Inhalt einer PN:
Zitat:

Zitat von Romber
Hallo jensw_2000!

ich bin mir nicht sicher, dass Sie sich noch daran errinern, aber vor einiger Zeit haben Sie mir bei der Lösung meines Problems sehr kompetent geholfen. Das war diesen Beitrag Login-Funktion: nur ein Benutzer mit bestimmten Zugangsdaten. Dort mit dem Beitrag #26 haben Sie mir die Lösung gepostet. Diese Lösung ist absoloute spitze, die verwende ich immer noch und es funktioniert super. Noch mal vielen Dank!

Ich stehe jetzt vor einer Aufgabe, die ich ohne Ihrer Hilfe ganz sicher nicht lösen kann. Und zwar geht es immer noch um diese SQL-Code, die Sie mir damals gepostet haben. Diese Code bzw. diese SP gewährleistet, dass nur ein Benutzer mit den bestimmten Zugangsdaten zur selber Zeit sich einloggen kann.

Mein Problem ist: ich muss die SQL-Code jetzt so umschreiben, dass sich max. 3 Benutzer mit den gleichen Zugangsdaten zur gleicher Zeit anmelden können. Leider habe ich von SQL nicht viel Ahnung und werde Ihnen sehr dankbar, wenn Sie mir dabei helfen würden.

P.S. Falls es viel Zeit braucht, würde ich natürlich gerne für Ihre Zeit bezahlen.

Im Voraus vielen Dank!

Für den Fall das jemand mal etwas Ähnliches benötigt, hänge ich den geänderten Code hier noch einmal komplett an.
Erklärungen zur Verwendung gibt es im Post #26.

Zitat:

Zitat von romber
P.S. Falls es viel Zeit braucht, würde ich natürlich gerne für Ihre Zeit bezahlen.

Ich hoffe das du mir auch mal hilfst, ohne gleich eine Rechnung zu schreiben :wink: .

DDL der Tabelle "SYS_ActiveUsers"
SQL-Code:
CREATE TABLE [SYS_ActiveUsers] (
  [USERNAME] varchar(50) NOT NULL,
  [Workstation] varchar(12) NOT NULL,
  [LAST_SEEN] datetime DEFAULT (getdate()) NOT NULL,
  [LOCK_TIME_SECS] int DEFAULT (600) NOT NULL
)
ON [PRIMARY]
GO
DDL der Stored Procedure "SYS_Check_User_LoginCount"
SQL-Code:
CREATE PROCEDURE SYS_Check_User_LoginCount
(
@USERNAME VARCHAR(50) = NULL,
@WORKSTATION VARCHAR(12) = NULL,
@LOGOUT BIT = NULL,
@AllowLogin BIT = 0 OUTPUT
)
AS
BEGIN

-- Variablen deklarieren

DECLARE @TEMPTIME DATETIME
DECLARE @TEMPDIFF INTEGER
DECLARE @MAXLOGINS INTEGER
DECLARE @CURRENTLOGINS INTEGER

-- Standardwerte setzen

SET @MAXLOGINS = 2  -- Ein Username kann sich von 2 unterschiedlichen Workstations anmenden
SET @CURRENTLOGINS = 0 -- @CURRENTLOGINS initialisieren

-- Parameter überprüfen

IF @USERNAME IS NULL OR @WORKSTATION IS NULL
BEGIN
  SET @AllowLogin = 0
  RAISERROR('Benutzername und Arbeitsstationsname müssen übermittelt werden',16,1,'SQL-Login')
END

-- Logout ??

IF @LOGOUT IS NULL SET @LOGOUT =0

IF @LOGOUT = 1
BEGIN
  -- Benutzer meldet sich regulär ab
  DELETE FROM SYS_ActiveUsers
        WHERE USERNAME=@USERNAME
          AND WORKSTATION=@WORKSTATION
  SET @AllowLogin=0
END
ELSE BEGIN


  IF EXISTS (
             SELECT USERNAME
             FROM SYS_ActiveUsers
             WHERE USERNAME=@USERNAME AND WORKSTATION = @WORKSTATION
            )
  BEGIN
    -- Relogin (selber User von der selben Workstation)
    -- Last_Seen Updaten und AllowLogin setzen
    UPDATE SYS_ActiveUsers SET LAST_SEEN = GETDATE()
    WHERE USERNAME=@USERNAME
          AND WORKSTATION=@WORKSTATION
    SET @AllowLogin=1
  END
  ELSE BEGIN
     -- Login des selben Users von einer anderen Workstation --

     -- Inaktive User (mit anderen Workstations) bereinigen,
     -- dann die Anzahl der Logins pro Username zählen.

     -- Prüfen, ob ein die Anzahl @MAXLOGINS für diesen User erreicht wurde.
     -- Wenn Anzahl der Logins <= @MAXLOGINS dann Login erlauben und Last_Seen setzen,
     -- sonst Login verweigern.

      -- inaktive User löschen
      DELETE
      FROM SYS_ActiveUsers
      WHERE USERNAME=@USERNAME
            AND WORKSTATION <> @WORKSTATION
            AND ABS( DATEDIFF( SECOND,LAST_SEEN,GETDATE() ) ) > LOCK_TIME_SECS

      -- Zählen, wie oft @USERNAME angemeldet ist ...
      SELECT @CURRENTLOGINS = Count(*)
      FROM SYS_ActiveUsers
      WHERE USERNAME=@USERNAME
      -- Wenn die Anzahl der Logins <= @MAXLOGINS dann User anmelden
      IF @CURRENTLOGINS < @MAXLOGINS
      BEGIN
        INSERT INTO SYS_ActiveUsers (USERNAME
                                    ,WORKSTATION
                                    ,LAST_SEEN
                                    ,LOCK_TIME_SECS)
                        VALUES     (@USERNAME
                                    ,@WORKSTATION
                                    ,GETDATE()
                                    ,600) -- Timeout Sekunden (Verfallszeit)
        SET @AllowLogin=1
      END
      ELSE BEGIN
        -- sonst Login verweigern
        SET @AllowLogin=0
      END
  END

END

END
GO

Delphi - Funktion um den User anzumelden, um das Login zu "Refreshen" und um den User anzumelden
Delphi-Quellcode:
var Authentificated : boolean;
...
...
function CheckLogin(Logout:Boolean): Boolean;
  var SP:TAdoStoredProc;
begin

SQL - Syntax Hinweis
-------------------------------------------- 
CREATE PROCEDURE SYS_Check_User_LoginCount

@USERNAME VARCHAR(50) = NULL,
@WORKSTATION VARCHAR(12) = NULL,
@LOGOUT BIT = NULL,
@AllowLogin BIT = 0 OUTPUT
)


  SP:=TAdoStoredProc.create(nil);
  SP.Connection:=MeineAdoConn; // Hier deine AdoConn
  try
    SP.Procedurename:='SYS_Check_User_LoginCount';
    SP.Parameters.refresh;
    SP.Parameters[1].Value:=MeinUserName;
    SP.Parameters[2].Value:=MeinPcName;
    if Logout then SP.Parameters[3].Value:=1 
      else SP.Parameters[3].Value:=0;
    SP.ExecProc;
    Result:=SP.Parameters[4].Value;
  finally
    FreeAndNil(SP);
  end;

  if Authentificated AND (NOT Logout) AND (NOT Result) then
  begin
    Showmessage('Ihr login wird gelöscht, weil von Ihrer Arbeitsstation keine "KeepAlive-Aufrufe"'+#13#10+ 
                'an die SP "SYS_Check_User_LoginCount" gesendet wurden, bzw. deren Timing nicht passt ...');
  end;

  if (NOT Authentificated) AND (NOT Result) then
  begin
    Showmessage('Die Anzahl der erlaubten Anmeldungen für "'+MeinUsername+'" ist überschritten.'+#13#10+ 
                'Bitte verwenden Sie einen anderen Benutzernamen oder versuchen Sie es später noch einmal.');
  end;

  Authentificated:=(NOT Logout) AND RESULT;

end;


Schöne Grüße,
Jens
:hi:


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:12 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz