USER/ADMIN LOGIN

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
fs1903
User
Beiträge: 7
Registriert: Sonntag 15. Dezember 2019, 14:54

Hallo miteinander,

ich bin bei meinem Uniprojekt hängen geblieben und komme nicht weiter. Für meine Website habe ich meine Datenbank verbunden. Registration sowie Userlogin funktioniert einwandfrei. Leider habe ich folgendes Problem, da wir vom Prof ins kalte Wasser geschmissen wurden fehlt mir die Erfahrung und mit Büchern, youtube videos usw.. komme ich leider nicht mehr weiter. Ich habe gefühlt seit tagen alles mögliche probiert, jedoch ohne Erfolg einen Adminlogin in meinen Loginprogress einzubauen. Ich würde mich sehr freuen wenn mir jemand einen Denkanstoß oder Lösungsansätze geben könnte. Meinen Adminbereich fürs User löschen habe ich fertig und muss nur noch in der python datei verlinkt werden.

Ich freue mich über Rückmeldungen und bedanke mich schonmal im vorraus :)))
Code:
@app.route('/login', methods=['GET', 'POST'])
def loginprogress():
if request.method == "GET":
# App-Route wurde direkt aufgerufen
return render_template("login.html") #kehre zur loginseite
# Übergabe der Daten aus dem Textfeld
log_benutzername = request.form["benutzername"]
log_passwort = request.form["passwort"]

# Wenn der Benutzername nicht eingegeben wurde
if log_benutzername is "":
flash("Bitte Benutzername und Passwort eingeben")
return redirect(url_for('index'))
# Wenn das Passwort nicht eingegeben wurde
if log_passwort is "":
flash("Bitte Passwort eingeben")
return redirect(url_for('index'))
# Überprüfen ob der Benutzername vorhanden ist
g.cur.execute("SELECT Benutzername, UserID FROM USERS where Benutzername = %s", (log_benutzername,))
db_id = g.cur.fetchone()

# Wenn der Name nicht vorhanden ist
if db_id is None:
flash("Benutzer exisitiert nicht")
#return render_template(page)
return redirect(url_for('index'))
#Überprüfen ob der Loginbenutzername mit dem Benutzername aus der DB übereinstimmt
if log_benutzername == db_id[0]:

#das Passwort aus der Datenbank holen
g.cur.execute("SELECT Passwort FROM USERS where Benutzername = %s", (log_benutzername,))
db_passwort = g.cur.fetchone()[0]
print(db_passwort)

#Überprüfen ob die gehashten Passwörter übereinstimmen
if check_password_hash(pwhash=db_passwort, password=log_passwort):
print(2)
session['log_benutzername'] = log_benutzername
session['UserID'] = db_id[1]
flash("Sie sind eingeloggt")
return redirect(url_for('benutzerseite'))

#Ausgabe wenn das Passwort falsch ist
print(3)
flash("Benutzername oder Passwort falsch")
#return render_template(page)
return redirect(url_for('index'))

# Ausgabe wenn der Benutzername falsch ist
flash("Benutzername oder Passwort falsch")
#return render_template(page)
return redirect(url_for('index'))
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

Was meinst Du mit "admin-login"? Wie unterscheidet der sich von einem normalen Login?

Zum Code:
`is` ist falsch zum vergleichen von Strings, das macht man mit ==.
Du solltest dem Nutzer nicht verraten, ob ein Nutzer existiert oder nicht, sondern nur, ob die Kombination User <-> Passwort korrekt ist.
Zwei SELECT-Abfragen, nur um beim zweiten mal das Passwort abzufragen, ist einer zu viel.
fs1903
User
Beiträge: 7
Registriert: Sonntag 15. Dezember 2019, 14:54

Danke Sirius3 für die schnelle antwort :)) hab meinen code jetzt überarbeitet. Ich hab zwar in der Datenbank Usern adminrechte gegeben mit einer 1 will das jedoch nicht in meinen Code mit hineinbeziehen. Ich will, dass wenn aus dem Loginformular benutzername = admin passwort = admin entnommen wird das programm die admin.html page öffnet. Hab das mit dem code if log_benutzername == "admin" and log_passwort =="admin":
flash("Hallo Admin")
return redirect(url_for('admin'))
versucht, jedoch hat es leider nicht funktioniert. zu dem hab ich versucht eine seperate loginpage anzulegen wo nur ein bestimmter sich anmelden kann. Doch leider hab ich das auch nicht hinbekommen, besser gesagt konnte die auftauchenden fehler nicht beheben.

nochmals vielen dank für deine Antwort :)
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

Was hast Du konkret versucht? Gesamter relevanter Code ist dazu nötig. Auch die Serverlogs.

Warum willst Du das Admin-Konto hart codiert haben, wo Du doch die Datenbank viel besser ist?
fs1903
User
Beiträge: 7
Registriert: Sonntag 15. Dezember 2019, 14:54

Mit der Datenbank hab ich das nicht hinbekommen. Da es nur noch 5 Wochen bis zu den Prüfungen sind muss ich so langsam meine Pythondatei loslassen. Ich hab mir gedacht, dass vllt diese Variante viel einfacher ist.

Code:
"""Minimale Flask Anwendung"""

# Import benötigter Flask-Module
from functools import wraps
import os
from flask import Flask, render_template, request, redirect, url_for, session,g, flash
from werkzeug.security import generate_password_hash , check_password_hash
import mysql.connector


# Import der Verbindungsinformationen zur Datenbank:
# Variable DB_HOST: Servername des MySQL-Servers
# Variable DB_USER: Nutzername
# Variable DB_PASSWORD: Passwort
# Variable DB_DATABASE: Datenbankname
from db.db_credentials import DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE

app = Flask(__name__)

# Secret-Key für Nutzung von Sessions
app.secret_key = os.urandom(24)

#DATENBANK VERBINDUNG AUFBAU
@app.before_request
def before_request():
g.con = mysql.connector.connect(host=DB_HOST,
user=DB_USER,
password=DB_PASSWORD,
database=DB_DATABASE)
g.cur = g.con.cursor()

@app.teardown_request
def teardown_request(exception):
cur = getattr(g, 'cur', None)
if cur is not None:
cur.close()
con = getattr(g, 'con', None)
if con is not None:
con.close()

@app.route('/register', methods=["GET", "POST"])
def register():
"""Registrieren"""
if request.method == "GET":
# App-Route wurde direkt aufgerufen
return render_template("register.html")
cur = g.con.cursor()
regname = request.form["name"]
regvorname = request.form["vorname"]
regemail = request.form["email"]
regbenutzername = request.form["Benutzername"]
regpasswort = request.form["Passwort"]

if regname == "":
error = 'Bitte Namen eingeben.'
flash(f'{error}')
return render_template("register.html")

if regvorname == "":
error = 'Bitte Vornamen eingeben.'
flash(f'{error}')
return render_template("register.html")

if regemail == "":
error = 'Bitte E-Mail eingeben.'
flash(f'{error}')
return render_template("register.html")

if regbenutzername == "":
error = 'Bitte Benutzernamen eingeben.'
flash(f'{error}')
return render_template("register.html")

if regpasswort == "":
error = 'Bitte Passwort eingeben.'
flash(f'{error}')
return render_template("register.html")

g.cur.execute("select * from USERS where Benutzername = %s", (regbenutzername,))
benutzernamedoppelt = g.cur.fetchone()

if benutzernamedoppelt is not None:
error = f'Benutzername "{regbenutzername}" wurde schon ausgewählt.'
flash(f'{error}')
return render_template("register.html")
g.cur.execute('SELECT * FROM USERS WHERE EMail = %s', (regemail,))
emaildoppelt = g.cur.fetchone()
if emaildoppelt is not None:
error = f'E-Mail "{regemail}" existiert bereits.'
flash(f'{error}')
return render_template("register.html")
g.x = generate_password_hash(regpasswort) #passwort hashen
#in die tabelle users hinzufügen
g.cur.execute("insert into USERS (Name,Vorname,EMail,Benutzername,Passwort,Passwortklartext,Admin) "
"values (%s, %s, %s, %s, %s, %s, 0)",
(regname, regvorname, regemail, regbenutzername,
generate_password_hash(regpasswort), regpasswort))
g.con.commit()
return render_template("index.html")

@app.route('/login', methods=['GET', 'POST'])
def loginprogress():
if request.method == "GET":
# App-Route wurde direkt aufgerufen
return render_template("login.html") #kehre zur loginseite
# Übergabe der Daten aus dem Textfeld
log_benutzername = request.form["benutzername"]
log_passwort = request.form["passwort"]

# Wenn der Benutzername nicht eingegeben wurde
if log_benutzername == "":
flash("Bitte Benutzername und Passwort eingeben")
return redirect(url_for('index'))
# Wenn das Passwort nicht eingegeben wurde
if log_passwort == "":
flash("Bitte Passwort eingeben")
return redirect(url_for('index'))
# Überprüfen ob der Benutzername vorhanden ist
g.cur.execute("SELECT Benutzername, UserID FROM USERS where Benutzername = %s", (log_benutzername,))
db_id = g.cur.fetchone()

# Wenn der Name nicht vorhanden ist
if db_id is None:
flash("Benutzer exisitiert nicht")
#return render_template(page)
return redirect(url_for('index'))
#Überprüfen ob der Loginbenutzername mit dem Benutzername aus der DB übereinstimmt
if log_benutzername == db_id[0]:

#das Passwort aus der Datenbank holen
g.cur.execute("SELECT Passwort FROM USERS where Benutzername = %s", (log_benutzername,))
db_passwort = g.cur.fetchone()[0]
print(db_passwort)

#Überprüfen ob die gehashten Passwörter übereinstimmen
if check_password_hash(pwhash=db_passwort, password=log_passwort):
print(2)
session['log_benutzername'] = log_benutzername
session['UserID'] = db_id[1]
flash("Sie sind eingeloggt")
return redirect(url_for('benutzerseite'))

#Ausgabe wenn das Passwort falsch ist
print(3)
flash("Benutzername oder Passwort falsch")
#return render_template(page)
return redirect(url_for('index'))

# Ausgabe wenn der Benutzername falsch ist
flash("Benutzername oder Passwort falsch")
#return render_template(page)
return redirect(url_for('index'))

@app.route('/logout', methods=['GET', 'POST'])
def logoutprogress():
# session.pop('log_benutzername', None)
# session.pop('userid', None)

values = list(session.keys())
print(values)
print(type)
for i in values:
session.pop(i)
flash("Sie sind ausgeloggt")
return redirect(url_for('index'))

@app.route('/Admin', methods=['POST', 'GET'])
def admin():
"""Startseite"""
return render_template('admin.html')

#Admin Anfang

# User löschen
@app.route('/deleteUser/<int:id>', methods=['POST'])
def deleteUser(id):
cur = g.con.cursor()
cur.execute(
"DELETE FROM USERS WHERE UserID=%s", (id,))
g.con.commit()
cur.close()
return redirect(url_for('adminuser'))

@app.route('/adminuser')
def adminuser():
g.cur.execute(
"Select * from USERS"
)
users = g.cur.fetchall()
return render_template('adminuser.html', users=users)


# Restaurants hinzufügen
@app.route('/admin', methods=['POST','GET'])
def restauranteingabe():
if request.method == 'POST':
# Formular wurde abgeschickt: Daten in DB speichern
restaurantname = request.form['restaurantname']
adresse = request.form['adresse']
postleitzahl = request.form['postleitzahl']
ort = request.form['ort']
info = request.form['info']

# typ = request.form['admin']
cur = g.con.cursor()
cur.execute("INSERT INTO RESTAURANTS (Restaurantname, Adresse, Postleitzahl, Ort, Info) VALUES (%s, %s, %s, %s, %s)",
(restaurantname, adresse, postleitzahl, ort, info))
g.con.commit()
cur.close()
return redirect(url_for('restauranteingabe'))
cur = g.con.cursor()
cur.execute("SELECT * FROM RESTAURANTS")
restaurant = cur.fetchall()
cur.close()
return render_template('admin.html', restaurant=restaurant)


# Restaurants löschen
@app.route('/deleteRestaurant/<int:id>', methods=['POST'])
def deleteRestaurant(id):
cur = g.con.cursor()
cur.execute(
"DELETE FROM RESTAURANTS WHERE RestaurantID=%s", (id,))
g.con.commit()
cur.close()
return redirect(url_for('restauranteingabe'))


@app.route('/editRestaurant/<int:id>', methods=['POST', 'GET'])
def editRestaurant(id):
if request.method == 'POST':
# Formular wurde abgeschickt: Daten in DB speichern

restaurantname = request.form['restaurantname']
adresse = request.form['adresse']
postleitzahl = request.form['postleitzahl']
ort = request.form['ort']
info = request.form['info']

cur = g.con.cursor()
cur.execute(
"UPDATE RESTAURANTS SET Restaurantname=%s, Adresse=%s, Postleitzahl=%s, Ort=%s, info=%s WHERE RestaurantID=%s",
(restaurantname, adresse, postleitzahl, ort, info, id,))
g.con.commit()
cur.close()
return redirect(url_for('restauranteingabe'))
cur = g.con.cursor()
cur.execute("SELECT * FROM RESTAURANTS WHERE RestaurantID=%s", (id,))
restaurant = cur.fetchall()
cur.close()
return render_template('edit_restaurant.html', restaurant=restaurant)
# Admin Ende

@app.route('/')
def index():
"""Startseite"""
return render_template('index.html')

@app.route('/agb')
def agb():
"""AGB"""
return render_template('agb.html')

@app.route('/about')
def about():
"""About"""
return render_template('about.html')

@app.route('/kontakt')
def contact():
"""Kontakt"""
return render_template('kontakt.html')


@app.route('/confirmation/<int:UserID>')
def validiereregisteremail(UserID):
g.cur.execute("Update USERS set confirmed = 1 where UserID = %s", (UserID,))
g.con.commit()
flash('Account verifiziert.')
return redirect(url_for('index'))

@app.route('/reservation')
def reservation():
"""Reservation"""
return render_template('reservation.html')

@app.route('/benutzerseite')
def benutzerseite():
"""Benutzerseite"""
return render_template('benutzerseite.html')

@app.route('/überuns')
def überuns():
"""Überuns"""
return render_template('überuns.html')

@app.route('/datenschutz')
def datenschutz():
"""Datenschutz"""
return render_template('datenschutz.html')

# Start der Flask-Anwendung
if __name__ == '__main__':
app.run(debug=True)

Datenbank (db_schema):
-- Tabellenstruktur für Tabelle `Users`

create table USERS (
UserID int PRIMARY KEY auto_increment,
Name varchar(25) NOT NULL ,
Vorname varchar(25) NOT NULL,
EMail varchar(50) NOT NULL,
Benutzername varchar(25) NOT NULL,
Passwort varchar(200) NOT NULL,
Passwortklartext varchar(30) not Null,
confirmed tinyint(1) default 0,
subscribed boolean default false,
Admin boolean
);

-- Daten für Tabelle 'USERS' (Daten hinzufügen)
-- Passworthash-->verschlüsselt Passwortklartext (sichtbar)

INSERT INTO USERS(UserID, Name, Vorname, EMail, Benutzername, Passwort,Passwortklartext, Admin) values (1, 'Ceylan', 'Pinar', 'pinarceylan@hotmail.de', 'Pinaruser1', 'Test1hash', 'Test1', '1');
INSERT INTO USERS(UserID, Name, Vorname, EMail, Benutzername, Passwort,Passwortklartext, Admin) values (2, 'Mueller', 'Schmidt', 'schmidtmueller@hotmail.de','schmidtuser2','Test2hash', 'Test2','2');

So sieht das bei mir gerade aus. Registration, Login und Logout funktioniert.

Danke Sirius03

Mit freundlichen Grüßen
fs1903
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

Statt jedes mal eine neue Datenbankverbindung aufzubauen, solltest Du ein Pool-Management verwenden, wie es beispielsweise SQLAlchemy zur Verfügung stellt.
Vermeide immer Abkürzungen in Variablennamen: con -> connection, cur -> cursor, regname -> registration_name, etc.
Keine *-SELECTs. Immer die konkreten Felder angeben, die man Abfragen will. In Zeile 79 ist das besser `SELECT count(*) ...`. Dass Benutzername und EMail eindeutig sein müssen, würde man aber besser durch entsprechende Constraints auf der Datenbank definieren und nicht händisch abfragen. Die SELECTS sind also überflüssig, und man fängt den entsprechenden Fehler beim INSERT ab. Alles andere ist eh unsicher, weil zwischen SELECT und INSERT theoretisch irgendwer anders einen Benutzer mit dem Namen anlegen könnte. Passwörter dürfen NIEMALS im Klartext in die Datenbank geschrieben werden.
Beim Login niemals zurückmelden, dass ein Benutzer nicht existiert. Dass Du das Passwort ein einem extra SELECT abfragst, hatten wir auch schon.
Beim logout: ein Dictionary kennt `clear`.
Im ganzen Admin-Bereicht prüfst Du nie, ob der eingeloggte User auch Admin-Rechte hat.
Zeile 212: über SELECT * hatte ich glaube ich schon was geschrieben.
/confirmation ist etwas zu simple, als dass das irgend etwas validieren würde. Da sollte ein Key generiert werden, den man nicht so einfach raten kann wie die User-ID.

Jetzt hast Du zwar geschrieben, was angeblich funktioniert, aber was funtioniert noch nicht und was hast Du versucht und welche Fehlermeldung kommt dann?
fs1903
User
Beiträge: 7
Registriert: Sonntag 15. Dezember 2019, 14:54

Wie gesagt wurden wir ins kalte Wasser geschmissen. Ich hab meine erste Bekanntschaft mit python vor 2 Monaten gemacht und mir Tag und Nacht versucht es selbst beizubringen, damit ich nicht durchfalle. Ich werde mich natürlich mit der Zeit weiterhin versuchen zu verbessern und notiere mir selbstverständlich ihre Tipps. Nur ist das Problem nicht der Code, sondern ich nicht weiss wie ich Adminrecht der User abfrage einbaue. Ich hab versucht es hart zu codieren wie sie es genannt haben, jedoch habe ich dabei keine Fehlermeldung bekommen, sondern am Ablauf hat sich nichts geändert und eine Benachrichtigung mit user nicht vorhanden wurde ausgegeben.

Ich will noch dazu sagen, dass ich mich noch nie mit mysql und python auseinandergesetzt habe und solche Fehler normal sind.

Bin noch ein ersti haha
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

Aber wie sieht denn der Code aus, den Du versucht hast und der nicht funktionierte?

Das einfachste wäre, das admin-Feld in session zu speichern und in den entsprechend Funktionen abzufragen.
fs1903
User
Beiträge: 7
Registriert: Sonntag 15. Dezember 2019, 14:54

if log_benutzername == "admin" and log_passwort == "admin":
flash("Hey, Admin")
return redirect(url_for('admin'))

diesen code hab ich in meinem Loginprogress versucht. Zu dem hab ich halt noch vieles versucht aus YouTube Tutorials nachzumachen aber hab es nicht verstanden oder nicht hinbekommen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

An welcher Stelle genau? Und bitte code-tags benutzen im vollstaendigen Editor, das ist der </>-Knopf.
fs1903
User
Beiträge: 7
Registriert: Sonntag 15. Dezember 2019, 14:54

Im app.route login unter der definition von log_passwort
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

Und kommst du in den if.-Block? Wirst Du an die richtige URL weitergeleitet? Wird dort dann die Seite ausgeliefert die du möchtest?
fs1903
User
Beiträge: 7
Registriert: Sonntag 15. Dezember 2019, 14:54

Nein, gefühlt überspringt python die Zeilen und öffnet die Index Seite, wobei er ausgibt, dass Benutzername und Passwort falsch sind.
Benutzeravatar
sparrow
User
Beiträge: 4502
Registriert: Freitag 17. April 2009, 10:28

Na das mit dem Fühlen ist so eine Sache beim Programmieren ;) Fühlen muss man nichts. Programmiersprachen machen in der Regel das, was man ihnen sagt.

Dann lass dir doch mal die Werte von log_benutzername und log_passwort ausgeben. Offensichtlich stimmen sie ja nicht mit dem überein, was du erwartest - sonst würden die Bedingungen ja erfüllt werden.
Alternativ prüfst do _vorher_ irgendwo das Login und hast dort keine Übereinstimmung und kommst gar nicht bis zu der Stelle.
Antworten