article

Tuesday, May 19, 2020

Flask Login Logout using SQLAlchemy with remember me COOKIE_TIME_OUT and password hash


Flask Login Logout using SQLAlchemy with remember me COOKIE_TIME_OUT and password hash

Database Table

CREATE TABLE user (
id INTEGER PRIMARY KEY,
username VARCHAR (64),
email VARCHAR (120),
fullname STRING (255),
password_hash VARCHAR (128),
about_me STRING (140),
last_seen DATETIME

);



#app.py
from flask import Flask, render_template, url_for, request, session, flash, redirect, make_response
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime, timedelta
from werkzeug.security import generate_password_hash, check_password_hash

app = Flask(__name__)

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

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///devdb.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.secret_key = "caircocoders-ednalan-2020"

db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    fullname = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))
    about_me = db.Column(db.String(140))
    last_seen = db.Column(db.DateTime, default=datetime.utcnow)
 
    def __repr__(self):
        return ''.format(self.username)
  
@app.route('/')
def index():
 if 'email' in session:
  username_session = session['email']
  user_rs = User.query.filter_by(email=username_session).first()
  return render_template('index.html', user_rs=user_rs)
 else:
  return redirect('/login')

@app.route('/login')
def login():
    passwordhash = generate_password_hash('test2')
    print(passwordhash)
    return render_template('login.html')
  
@app.route('/submit', methods=['POST'])
def login_submit():
 _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') 
  row = User.query.filter_by(email=username).first()
  if row and check_password_hash(row.password_hash, password):
   #print(username + ' ' + password)
   session['email'] = row.email
   return redirect('/')
  else:
   return redirect('/login')
 # validate the received values
 elif _email and _password:
  #check user exists   
  row = User.query.filter_by(email=_email).first()  
  if row:
   if check_password_hash(row.password_hash, _password):
    session['email'] = row.email
    if _remember:
     resp = make_response(redirect('/'))
     resp.set_cookie('email', _email, 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)
//templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Home</title>
</head>
<body>
<p align="center"><h1>Python Flask Login Logout</h1></p>
<p align="center"><h1>Hello : {{ user_rs.fullname }}</h1></p>
<p><h3><a href="{{ url_for('logout') }}">Log Out</a></h3></p>
</body>
</html>
//templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Login</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css">
</head>
<body>
<div class="container">
    <div class="card card-login mx-auto text-center bg-dark">
        <div class="card-header mx-auto bg-dark">
            <span> <img src="{{ url_for('static', filename='img/logologin.png') }}" class="w-75" alt="Logo"> </span><br/>
            <span class="logo_title mt-5"> Login Dashboard </span>
    <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>
        <div class="card-body">
            <form method="post" action="/submit">
                <div class="input-group form-group">
                    <div class="input-group-prepend">
                        <span class="input-group-text"><i class="fas fa-user"></i></span>
                    </div>
                    <input type="text" name="inputEmail" class="form-control" value="{% if 'email' in request.cookies %} {{ request.cookies.get('email') }} {% endif %}" placeholder="Email Address">
                </div>

                <div class="input-group form-group">
                    <div class="input-group-prepend">
                        <span class="input-group-text"><i class="fas fa-key"></i></span>
                    </div>
                    <input type="password" name="inputPassword" class="form-control" value="{% if 'pwd' in request.cookies %} {{ request.cookies.get('pwd') }} {% endif %}" placeholder="Password">
                </div>
    
    <div class="input-group 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" style="color:#fff;">Remember me</label>
       </div>
    </div>
                <div class="form-group">
                    <input type="submit" name="btn" value="Login" class="btn btn-outline-danger float-right login_btn">
                </div>

            </form>
        </div>
    </div>
</div>
<style>
body {
            background: #17a2b8 !important;
        }
        .card {
            border: 1px solid #28a745;
        }
        .card-login {
            margin-top: 130px;
            padding: 18px;
            max-width: 30rem;
        }

        .card-header {
            color: #fff;
            /*background: #ff0000;*/
            font-family: sans-serif;
            font-size: 20px;
            font-weight: 600 !important;
            margin-top: 10px;
            border-bottom: 0;
        }

        .input-group-prepend span{
            width: 50px;
            background-color: #ff0000;
            color: #fff;
            border:0 !important;
        }

        input:focus{
            outline: 0 0 0 0  !important;
            box-shadow: 0 0 0 0 !important;
        }

        .login_btn{
            width: 130px;
        }

        .login_btn:hover{
            color: #fff;
            background-color: #ff0000;
        }

        .btn-outline-danger {
            color: #fff;
            font-size: 18px;
            background-color: #28a745;
            background-image: none;
            border-color: #28a745;
        }

        .form-control {
            display: block;
            width: 100%;
            height: calc(2.25rem + 2px);
            padding: 0.375rem 0.75rem;
            font-size: 1.2rem;
            line-height: 1.6;
            color: #28a745;
            background-color: transparent;
            background-clip: padding-box;
            border: 1px solid #28a745;
            border-radius: 0;
            transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
        }

        .input-group-text {
            display: -ms-flexbox;
            display: flex;
            -ms-flex-align: center;
            align-items: center;
            padding: 0.375rem 0.75rem;
            margin-bottom: 0;
            font-size: 1.5rem;
            font-weight: 700;
            line-height: 1.6;
            color: #495057;
            text-align: center;
            white-space: nowrap;
            background-color: #e9ecef;
            border: 1px solid #ced4da;
            border-radius: 0;
        }
</style>
</body>
</html>

Related Post