Search code examples
pythonauthenticationstreamlit

in my python code User Getting to Click Login button Twice, But user should only need to click the login button once to log in


Hello fellow developers,

I am encountering an issue with my script and would greatly appreciate any assistance. My script runs successfully and executes the login() function without any errors. However, I have noticed that after entering my credentials and clicking on the login button, I am not able to log in on the first attempt. It requires me to click the login button twice before I can access my main application.

This behavior is unexpected and I am unsure how to resolve it. I have double-checked my code and confirmed that there are no syntax errors or logical issues that could be causing this problem.

Has anyone else encountered a similar issue before? If so, could you please share your insights on how to resolve this problem? I would greatly appreciate any suggestions or tips that could help me get to the bottom of this issue and achieve a seamless login experience for my users.

Thank you in advance for your time and assistance.

import streamlit as st
import mysql.connector
import configparser
import hashlib
import time


# Define SessionState class to store state information
class SessionState:
    def __init__(self, **kwargs):
        self.hash_funcs = {"_CodeHasher": lambda x: None}
        self.__dict__.update(kwargs)


# Define a function to hash passwords
def hash_password(password):
    salt = hashlib.sha256(str.encode(password)).hexdigest()[:10]
    hashed_password = hashlib.sha256(str.encode(salt + password)).hexdigest() + ':' + salt
    return hashed_password


# Define a function to check if a password matches a hashed password
def check_password(password, hashed_password):
    try:
        stored_password, salt = hashed_password.split(':')
    except ValueError:
        return False
    return stored_password == hashlib.sha256(str.encode(salt + password)).hexdigest()


# Define a function to authenticate users
def authenticate(email, password):
    cursor = mydb.cursor()
    query = "SELECT email, password FROM users WHERE email=%s"
    cursor.execute(query, (email,))
    result = cursor.fetchone()
    if result:
        stored_email, stored_password = result
        if check_password(password, stored_password):
            return stored_email
        return False


# Define a function to create a new user
def create_user(name, email, password):
    cursor = mydb.cursor()
    hashed_password = hash_password(password)
    query = "INSERT INTO users (name, email, password) VALUES (%s, %s, %s)"
    cursor.execute(query, (name, email, hashed_password))
    mydb.commit()

    return cursor.lastrowid


# Read the configuration file
config = configparser.ConfigParser()
config.read('config.ini')

# Retrieve the database settings from the configuration file
database_user = config.get('database', 'user')
database_password = config.get('database', 'password')
database_host = config.get('database', 'host')
database_name = config.get('database', 'database')







# --------- User Authentication -------

# Read the configuration file
config = configparser.ConfigParser()
config.read('config.ini')

# Connect to the database using the settings from the configuration file
mydb = mysql.connector.connect(user=database_user, password=database_password, host=database_host,
                               database=database_name)

# Set the Streamlit page configuration
st.set_page_config(page_title="Chitti 2.0", page_icon=":guardsman:", layout="wide")


# Define the login page
def login():
    # Center the login form
    st.markdown("<h1 style='text-align: center;'>Login</h1>", unsafe_allow_html=True)
    email = st.text_input("Email")
    password = st.text_input("Password", type="password")
    # Apply styling to the login button
    st.write('<style>div.row-widget.stButton > button {width: 100%;}</style>', unsafe_allow_html=True)
    if st.button("Login"):
        if email and password:
            with st.spinner('Logging in...'):
                user = None
                while user is None:
                    user = authenticate(email, password)
                    time.sleep(1)
                st.session_state.user = user
                st.success("Logged in successfully!")
    return None


# Define the signup page
def signup():
    st.header("Sign Up")
    name = st.text_input("Name")
    email = st.text_input("Email", key="signup_email")
    password = st.text_input("Password", type="password")
    confirm_password = st.text_input("Confirm Password", type="password")
    if password != confirm_password:
        st.error("Passwords do not match")
    elif st.button("Sign Up"):
        create_user(name, email, password)
        st.success("User created")
    else:
        return None


# Define the Logout
def logout():
    st.session_state.pop("user", None)
    st.success("Logged out successfully")


def main():
    # Display the main page if the user is logged in
    if not hasattr(st.session_state, 'user'):
        login()
        return None
    else:
        st.write("Main APP")

if __name__ == '__main__':
    main()

Please help me to Fix this.

Using Streamlit, for my UI


Solution

  • This is an internal page jump operation, implemented in the script way

    Re-execute the script after successful login

    
    def login():
        # Center the login form
        st.markdown("<h1 style='text-align: center;'>Login</h1>", unsafe_allow_html=True)
        email = st.text_input("Email")
        password = st.text_input("Password", type="password")
        # Apply styling to the login button
        st.write('<style>div.row-widget.stButton > button {width: 100%;}</style>', unsafe_allow_html=True)
        if st.button("Login"):
            if email and password:
                with st.spinner('Logging in...'):
                    user = None
                    while user is None:
                        user = authenticate(email, password)
                        time.sleep(1)
                    st.session_state.user = user
                    st.success("Logged in successfully!")
    
                    st.experimental_rerun()
        return None