Jak zaimplementować logowanie?

Jak zaimplementować logowanie?
Kamil Zarebski
  • Rejestracja:prawie 2 lata
  • Ostatnio:prawie 2 lata
  • Postów:1
0

Witam mam pewien problem ze stworzeniem działającego panelu logowania na mojej stronie a dokładniej z funkcją check_password_hash biblioteki werkzeug.security, mianowicie funkcja rejestracji działa poprawnie, dane są wysyłane do bazy danych oraz zapisywane w niej a samo hasło jest hashowane. Problem pojawia się jednak przy samym logowaniu, ponieważ mimo iż wpisuje poprawne hasło to nie zostaje rozpoczęta sesja. Poniżej zostawiam kod być może znajdzie się jakaś dobra duszyczka chcąca mi pomóc :). Dodam także że korzystam z aktualnej wersji python oraz werkzeug.
Funkcja rejestracji:

Kopiuj
@app.route('/api/register', methods =['POST'])
def registerf():
    try:
        if request.method == 'POST':
            username = request.form['username']
            name = request.form['name']
            email = request.form['email']
            password = request.form['password']
            if username and name and email and password:
                conn = mysql.connect
                cursor = conn.cursor()
                hashed_pass = generate_password_hash(password, method='pbkdf2', salt_length=16)
                cursor.callproc('sp_createUser', (username, hashed_pass, name, email))
                data = cursor.fetchall()
                if len(data) == 0:
                    conn.commit()
                    return redirect(url_for('login'))
                else:
                    return json.dumps({'msg': 'error'})
            else:
                return json.dumps({'html': '<span>error </span>'})
    except Exception as e:
        return json.dumps({'error': str(e)})
    finally:
        cursor.close()
        conn.close()
Funkcja logowania: 
@app.route('/api/login', methods=['POST'])
def loginf():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        cursor = mysql.connection.cursor()
        cursor.callproc('sp_validateLogin', (username,))
        account = cursor.fetchone()
        if account:
            if check_password_hash(account['Haslo'], password):
                session.permanent = True
                session['loggedin'] = True
                session['id'] = account['id']
                session['username'] = account['Login']
                cursor.close()
                return redirect('/home')
            else:
                return redirect('/login')
        else:
            return redirect('/register')

PROCEDURA BAZY DANYCH sp_validateLogin

BEGIN
    select * from uzytkownik where login = username;
END
edytowany 4x, ostatnio: Kamil Zarebski
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:2 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
0

Sformatuj najpierw kod bo nic nie widać .
W MD kod sie formatuje za pomoca ```


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
edytowany 1x, ostatnio: KamilAdam
Kamil Zarebski
już powinno być okej.
enedil
  • Rejestracja:prawie 12 lat
  • Ostatnio:dzień
  • Postów:1027
0
Kopiuj
conn = mysql.connect

czy ty w ogóle dałeś nam kod który się uruchamia? Bo to w kolejnej linijce się wywali.

edytowany 2x, ostatnio: Riddle
Kamil Zarebski
Tak kod się uruchamia, funkcja odpowiedzialna za rejestracje użytkownika i przesłanie danych do bazy danych działa i nie widzę większych problemów na etapie którym jestem, a sama opcja mysql.connect działa. Funkcja logowania także łączy się bez problemu z bazą danych wyszukuje użytkownika po wpisanej nazwie, błąd jednak występuje w momencie gdy dodaje opcję hasła i próbuje porównać je z tym bazo danowym. Powyżej zostawiam wersję lekko zmodyfikowanego kodu odpowiedzialnego za funkcje logowania.
KR
  • Rejestracja:ponad 3 lata
  • Ostatnio:3 miesiące
  • Postów:53
2

Będzie łatwiej Ci pomóc kiedy podasz treść błędu, wartość zmiennej account, treść procedury sp_validateLogin i funkcji check_password_hash.

Kamil Zarebski
Błąd występuje w momencie dodania funkcji odpowiedzialnej za porównanie hashu hasła z bazy danych z hasłem wpisanym przez użytkownika, mianowicie mimo iż podaje prawidłowe hasło program zczytuje je jako nie prawidłowe. Sam w sobie błąd, który wykrywa debugger nie występuje. Wartością zmiennej account jest wynik procedury sp_validateLogin, którą dodałem już w zmodyfikowanym poście, a dokładniej mówiąc jest nią rekord z tabeli użytkownik wyszukiwany na podstawie podanej przez użytkownika nazwy loginu przechowujący dane takie jak hasło itd. A funkcja check_password_hash 1/2
Kamil Zarebski
2/2 jest funkcją biblioteki werkzeug która porównuje wcześniej zahashowane hasło funkcją generate_password_hash, wrzucone do bazy danych przy rejestracji z tym podawanym podczas logowania.
KE
  • Rejestracja:ponad 6 lat
  • Ostatnio:20 minut
  • Postów:684
0

Za duży zakres testujesz, niepotrzebnie przechodzisz poprzez warstwę HTTP, może tam jest błąd, gdzieś whitespace wpada, pole się źle koduje etc.
Proponuję w jednym bloku kodu (np. dodaj nowy endpoint /test) wykonać generate_password_hash a potem od razu check_password_hash na wyniku tej poprzedniej funkcji. Wykluczysz potencjalne błędy wokoło tego kodu (który jak sam mówisz, zmodyfikowałeś, więc może w ogóle to nie ma sensu :P).

MA
  • Rejestracja:około 5 lat
  • Ostatnio:prawie 2 lata
  • Postów:134
1

@Kamil Zarebski:
Użycie generate_password_hash oraz check_password_hash wygląda ok.
Sprwadź:

  1. Czy procedury sp_createUser oraz sp_validateLogin robią co należy z pozycji mysql call sp_*(...)

  2. Zobacz czy hash prawidłowo zapisuje się w bazie.
    W tym celu pobierasz selectem w mysql rekord z hashem i możesz porównać z tym co Ci wyjdzie z tym (możesz wykonać z pozycji interpretera):

    Kopiuj
    from werkzeug.security import _hash_internal
    hash,method = _hash_internal('pbkdf2','tutaj_salt_to_pomiedzy_znakami_$','haslo')
    print(hash)
    

    Być może baza danych coś tam ucina?

  3. Wyświetl co znajduje się w account z loginf tak jak pisał Ci @Krzemień. Sprawdź czy korzystasz z DictCrusor, bo odwołujesz się tak jakbyś korzystał.

  4. Sprawdź konfigurację sesji, może wydaje Ci się że problem jest w tej funkcji, a tak na prawdę jest w innym miejscu?

Uwagi:

  1. Dlaczego w loginf zamykasz cursor (linia 42) za ifem? Korzystaj z with lub try/finally.
  2. Mam nadzieję, że ta implementacja sesji to jest taka tylko przykładowa.
  3. Dlaczego z API (może że to tylko tak dla zmyłki) robisz redirecty? Albo zwracaj czysty json i obsługuj to na poziomie frontu, albo jakoś to sensownie wydziel (jak już musisz).
  4. Staraj się przekazywać pełny, możliwy do reprodukcji przykład, a nie jakiegoś "wymieszańca". Bo tak jak to podałeś, to można tylko się domyślać, nikt tego nie będzie poprawiał za Ciebie.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.