article

Sunday, February 23, 2020

Python Flask Mysql Login Logout with Remember Me Option and Password Hash


Python Flask Mysql Login Logout with Remember Me Option and Password Hash


This tutorial we are going to see how to give users to remember their login credentials through cookie and password in the database is in hash

Database Table

CREATE TABLE `user_test_flask` (
  `id` int(10) UNSIGNED NOT NULL,
  `name` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `username` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
  `email` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `pwd` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `admin` tinyint(4) DEFAULT '0',
  `last_login` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Dumping data for table `user_test_flask`

INSERT INTO `user_test_flask` (`id`, `name`, `username`, `email`, `pwd`, `admin`, `last_login`) VALUES

(1, 'Cairocoders Ednalan', 'test2', 'test2@gmail.com', 'pbkdf2:sha256:150000$QYp0kc3v$88fb99cca1479b212dfdf7f58199e7207693a9cc187065b7dbe7837f3cd4872c', 0, '2020-02-22 02:26:21')

ALTER TABLE `user_test_flask`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `user_test_flask`
  MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;

Login
Email : test2@gmail.com
Password : test2


#app.py
from flask import Flask, render_template, url_for, flash, session, request, redirect, make_response
from flaskext.mysql import MySQL
import pymysql
from datetime import timedelta
from werkzeug import generate_password_hash, check_password_hash

app = Flask(__name__)

app.secret_key = "caircocoders-ednalan-2020"
app.config['PERMANENT_SESSION_LIFETIME'] =  timedelta(minutes=10)

global COOKIE_TIME_OUT
#COOKIE_TIME_OUT = 60*60*24*7 #7 days
COOKIE_TIME_OUT = 60*5 #5 minutes

#Database Configuration
mysql = MySQL()

# MySQL configurations
app.config['MYSQL_DATABASE_USER'] = 'root'
app.config['MYSQL_DATABASE_PASSWORD'] = ''
app.config['MYSQL_DATABASE_DB'] = 'testingdb'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'
mysql.init_app(app)

@app.route('/')
def index():
 if 'email' in session:
  username = session['email']
  return 'Logged in as ' + username + '<br>' + "<b><a href = '/logout'>Click here to logout</a></b>"
 return "You are not logged in <br><a href = '/login'></b>" + "click here to login</b></a>"
 
@app.route('/login')
def login():
 return render_template('login_logout_with_rememberme.html')

@app.route('/submit', methods=['POST'])
def login_submit():
 conn = None
 cursor = None
 
 _email = request.form['inputEmail']
 _password = request.form['inputPassword']
 _remember = request.form.getlist('inputRemember')
 
 if 'email' in request.cookies:
  username = request.cookies.get('email')
  password = request.cookies.get('pwd')
  conn = mysql.connect()
  cursor = conn.cursor()
  sql = "SELECT * FROM user_test_flask WHERE email=%s"
  sql_where = (username,)
  cursor.execute(sql, sql_where)
  row = cursor.fetchone()
  if row and check_password_hash(row[4], password):
   print(username + ' ' + password)
   session['email'] = row[3]
   cursor.close()
   conn.close()
   return redirect('/')
  else:
   return redirect('/login')
 # validate the received values
 elif _email and _password:
  #check user exists   
  conn = mysql.connect()
  cursor = conn.cursor()
  sql = "SELECT * FROM user_test_flask WHERE email=%s"
  sql_where = (_email,)
  cursor.execute(sql, sql_where)
  row = cursor.fetchone()
  if row:
   if check_password_hash(row[4], _password):
    session['email'] = row[3]
    cursor.close() 
    conn.close()
    if _remember:
     resp = make_response(redirect('/'))
     resp.set_cookie('email', row[3], max_age=COOKIE_TIME_OUT)
     resp.set_cookie('pwd', _password, max_age=COOKIE_TIME_OUT)
     resp.set_cookie('rem', 'checked', max_age=COOKIE_TIME_OUT)
     return resp
    return redirect('/')
   else:
    flash('Invalid Password!')
    return redirect('/login')
  else:
   flash('Invalid Email Or Password!')
   return redirect('/login')
 else:
  flash('Invalid Email Or Password!')
  return redirect('/login')
  
@app.route('/logout')
def logout():
 if 'email' in session:
  session.pop('email', None)
 return redirect('/')
 
if __name__ == '__main__':
 app.run(debug=True)

//login_logout_with_rememberme.html
<html>
<title>Python Flask Mysql Login Logout with Remember Me Option and Password Hash</title>
 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
 <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css">
</head>
<body>
 <div class="container h-100">
  <h4 align="center">Python Flask Mysql Login Logout with Remember Me Option and Password Hash</h4>
  <div class="d-flex justify-content-center h-100">
   <div class="user_card">
    <div class="d-flex justify-content-center">
     <div class="brand_logo_container">
      <img src="{{ url_for('static', filename='img/logo.png') }}" class="brand_logo" alt="Logo">
     </div>
    </div>
    <div class="d-flex justify-content-center form_container">
     <form method="post" action="/submit">
      <div class="input-group mb-3">
       <div class="input-group-append">
        <span class="input-group-text"><i class="fas fa-user"></i></span>
       </div>
       <input type="text" name="inputEmail" value="{% if 'email' in request.cookies %} {{ request.cookies.get('email') }} {% endif %}" placeholder="Email" required class="form-control input_user">
      </div>
      <div class="input-group mb-2">
       <div class="input-group-append">
        <span class="input-group-text"><i class="fas fa-key"></i></span>
       </div>
       <input type="password" name="inputPassword" value="{% if 'pwd' in request.cookies %} {{ request.cookies.get('pwd') }} {% endif %}" placeholder="Password" autocomplete="off" required class="form-control input_pass" value="">
      </div>
      <div class="form-group">
       <div class="custom-control custom-checkbox">
        <input type="checkbox" name="inputRemember" checked="{% if 'rem' in request.cookies %} {{ request.cookies.get('rem') }} {% endif %}" autocomplete="off" class="custom-control-input" id="customControlInline">
        <label class="custom-control-label" for="customControlInline">Remember me</label>
       </div>
      </div>
       <div class="d-flex justify-content-center mt-3 login_container">
       <input type="submit" value="Login" class="btn login_btn">
       </div>
     </form>
    </div>
  
    <div class="mt-4">
    <div>
     {% with messages = get_flashed_messages() %}
       {% if messages %}
      {% for message in messages %}
      <div class="alert alert-danger" role="alert">{{ message }}</div>
      {% endfor %}
       {% endif %}
     {% endwith %}
    </div>
     <div class="d-flex justify-content-center links">
      Don't have an account? <a href="#" class="ml-2">Sign Up</a>
     </div>
     <div class="d-flex justify-content-center links">
      <a href="#">Forgot your password?</a>
     </div>
    </div>
   </div>
  </div>
 </div>
<style>
  body,
  html {
   margin: 0;
   padding: 0;
   height: 100%;
   background: #60a3bc !important;
  }
  .user_card {
   height: 450px;
   width: 350px;
   margin-top: auto;
   margin-bottom: auto;
   background: #f39c12;
   position: relative;
   display: flex;
   justify-content: center;
   flex-direction: column;
   padding: 10px;
   box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
   -webkit-box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
   -moz-box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
   border-radius: 5px;

  }
  .brand_logo_container {
   position: absolute;
   height: 170px;
   width: 170px;
   top: -75px;
   border-radius: 50%;
   background: #60a3bc;
   padding: 10px;
   text-align: center;
  }
  .brand_logo {
   height: 150px;
   width: 150px;
   border-radius: 50%;
   border: 2px solid white;
  }
  .form_container {
   margin-top: 100px;
  }
  .login_btn {
   width: 100%;
   background: #c0392b !important;
   color: white !important;
  }
  .login_btn:focus {
   box-shadow: none !important;
   outline: 0px !important;
  }
  .login_container {
   padding: 0 2rem;
  }
  .input-group-text {
   background: #c0392b !important;
   color: white !important;
   border: 0 !important;
   border-radius: 0.25rem 0 0 0.25rem !important;
  }
  .input_user,
  .input_pass:focus {
   box-shadow: none !important;
   outline: 0px !important;
  }
  .custom-checkbox .custom-control-input:checked~.custom-control-label::before {
   background-color: #c0392b !important;
  }
</style> 
</body>
</html>

Related Post