Personal account in flask

时间:2018-02-03 08:33:46

标签: jquery python ajax flask jinja2

I am trying to implement enter to personal account on my web app in Flask.

Scheme is as follows:

  • user types 'login' and 'password' and hit enter
  • Ajax requests executes through jQuery to python script after hitting enter
  • python function validate_user() executes after than which after database request return true or false
  • in case of false - user is invalid and connection drops; if true the next ajax requests executes to another python function user_login()
  • this function accumulates all data by user and makes redirect to personal_account lage, which loads private.html and some plot must accour and some user data as well

The problem is in the last step, when redirect to /personal_account does not properly work and URL does not change and js does not connect and instead of private.html there is code of page where user was when he tries to enter to personal account (button enter_to_account is on every page of flask app)

private.html 
{% block tab_content %}
    <canvas width="800" height="600" id="canvas"></canvas>
    <script>
        window.onload = init;
        function init(){
            console.log('работает');
            var canvas = document.getElementById('canvas');
            if (canvas) {
                if (canvas.getContext) {
                    var ctx = canvas.getContext('2d');

                    ctx.fillRect(25, 25, 100, 100);
                }
            }
        }
    </script>
{% endblock %}

function validate_user()

@app.route('/validate_user', methods=['POST'])
def validate_user():
    login = request.form['login']
    password = request.form['password']

    try:
        c, conn = cursor_connection()
        c = conn.cursor()
        c.execute("SELECT hsh "
                  "FROM auth_info "
                  "WHERE login='{}'  ; "
                  "".format(login, password))

        res = c.fetchall()[0][0]
        c.close()
        conn.close()

    except Exception as e:
        logger.info(msg='Failed to execute /validate_user {}'.format(e))
        return render_template('500.html')

    if check_password_hash(password=password, pwhash=res):
        return jsonify({'result': True})
    return jsonify({'result': False})

function user_login()

@app.route('/user_login', methods=['POST'])
def user_login():
    login = request.form['login']
    if login is None or not login:
        return jsonify(data='Incorrect URL')

    try:
        c, conn = cursor_connection()
        c = conn.cursor()
        c.execute("SELECT accounts_info_uid "
                  "FROM auth_info WHERE login='{}' ".format(login))

        id = c.fetchall()
        if not id:
            return jsonify(data='Incorrect login')

        c.execute("SELECT * FROM boxes_id AS tb1 LEFT JOIN"
                  " accounts_info AS tb2 ON tb2.boxes_ids=tb1.uid "
                  # "LEFT JOIN electricity_info as tb3 ON tb3.boxes_id_uid=tb1.uid"
                  " WHERE tb2.uid={} ".format(id[0][0]))

        uid, mc_address, working_status, activation_status, _,\
        first_name, second_name, registration_date, phone, email, boxes_id = c.fetchall()[0]
        c.execute(" SELECT consumed_electricity "
                  "FROM electricity_info "
                  "WHERE boxes_id_uid={} ".format(boxes_id))
        consumed_electricity = [float(val[0]) for val in c.fetchall()]
        c.close()
        conn.close()

    except Exception as e:
        logger.error(msg='Cannot execute /user_login {}'.format(e))
        return str(e)

    user = User()
    user.id = login
    login_user(user)
    return redirect(url_for('welcome'))

welcome page:

@app.route('/welcome')
def welcome():
    return render_template('private.html')#'You are on welcome page'

Used tech: flask, python 2.7, jinja2, ajax

Please tell me what is the issue here and how to handle it?

Thank you!

EDIT ONE

code of double-ajax request

common.js:

document.getElementById('next_in').onclick = function (){  //after hitting enter
    $.ajax({
        data: {
            login: document.getElementById('log').value,
            password: document.getElementById('pass').value
        },
        type: 'POST',
        url: '/validate_user',
        success: function (data_1) {
            if(data_1.result==true){
                $.ajax({
                    data: {
                        login: document.getElementById('log').value
                    },
                    type: 'POST',
                    url: '/user_login',
                    success: function (data_2) {
                        document.body.innerHTML = data_2;
                    }

                });
            }
            else{
                alert('Incorrect user or login!');
            }
        }
    });
}

plot inside of private.html:

<script>
        window.onload = init;
        function init(){
            console.log('работает');
            var canvas = document.getElementById('canvas');
            if (canvas) {
                if (canvas.getContext) {
                    var ctx = canvas.getContext('2d');

                    ctx.fillRect(25, 25, 100, 100);
                }
            }
        }


 </script>

EDIT TWO

Allow myself to clarify wanted result once again.

I want redirect to 'pure' private.hrml as well as redirect to 'pure' URL /welcome

1 个答案:

答案 0 :(得分:1)

This is not how you authenticate a user. You should never trust the client with anything regarding the auth, and here you basically verify the database response in your Javascript code. Not to mention the private.html page, which is right now accessible at the /welcome endpoint without any checks at all: try typing http://localhost:5000/welcome in your browser if you're using the default Flask settings.

You might find helpful this SO post, which gives an overview of the typical cookie auth.

The Flask-Login library (which you actually have installed) provides some of the most common session management functions.

That being said, if you want to “make it work” with a simple one-page restricted area, here's what you might do:

  • Throw out all the AJAX requests
  • Make the user send the login data directly to /welcome
  • Combine all Flask endpoints into one at /welcome, verify and output data in a single request.

Example implementation:

from flask import *

app = Flask(__name__)

def verify(login, password) -> bool:
    """Query the database and return True iff there is 
    a user record with matching credentials. """
    return True

def get_user_data(login) -> dict:
    """Query the database for consumed electricity from user. """
    return {
        'first_name': 'User',
        'last_name': 'McUser',
        'consumed_electricity': 100.0
    }

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

@app.route('/welcome', methods=['POST'])
def welcome():
    login = request.form['login']
    password = request.form['password']
    if not verify(login, password):
        abort(403)
    data = get_user_data(login)
    return render_template('private.html', data=data)

index.html source:

<form action="/welcome" method="post">
    Login: <input type="text" name="login"> <br>
    Password: <input type="password" name="password"> <br>
    <input type="submit" value="Log In">
</form>

private.html source:

<ul>
    <li>{{ data.first_name }}</li>
    <li>{{ data.last_name }}</li>
    <li>{{ data.consumed_electricity }}</li>
</ul>