【问题标题】:Flask - MongoDB - Protect routesFlask - MongoDB - 保护路由
【发布时间】:2021-04-06 01:06:25
【问题描述】:

我是 Flask 的新手,我使用 Flask 构建了一个基本的 Web 应用程序。此应用程序将由单个用户使用。用户必须连接才能访问任何路由。在我的应用上创建新路由并确保用户在能够访问该页面之前已登录的最简单、最安全的方法是什么?

我添加了这条路线,即使我已经登录也可以访问该页面。

@login_required
@app.route('/secret')
def secret():
    return "hello world"

app.py

from flask import Flask, render_template, url_for, request, session, redirect
from flask_pymongo import PyMongo
import bcrypt

app = Flask(__name__)

app.config['MONGO_DBNAME'] = xxx'
app.config['MONGO_URI'] = 'xxxx'

mongo = PyMongo(app)

@app.route('/')
def index():
    if 'username' in session:
        return 'You are logged in as ' + session['username']

    return render_template('index.html')

@app.route('/login', methods=['POST'])
def login():
    users = mongo.db.users
    login_user = users.find_one({'name' : request.form['username']})

    if login_user:
        if bcrypt.hashpw(request.form['pass'].encode('utf-8'), login_user['password']) == login_user['password']:
            session['username'] = request.form['username']
            return redirect(url_for('index'))

    return 'Invalid username/password combination'

@app.route('/register', methods=['POST', 'GET'])
def register():
    if request.method == 'POST':
        users = mongo.db.users
        existing_user = users.find_one({'name' : request.form['username']})

        if existing_user is None:
            hashpass = bcrypt.hashpw(request.form['pass'].encode('utf-8'), bcrypt.gensalt())
            users.insert({'name' : request.form['username'], 'password' : hashpass})
            session['username'] = request.form['username']
            return redirect(url_for('index'))
        
        return 'That username already exists!'

    return render_template('register.html')

@app.route('/logout')
def logout():
    session.pop('username', None)
    return render_template('index.html')

if __name__ == '__main__':
    app.secret_key = 'mysecret'
    app.run(debug=True, port='3500')

【问题讨论】:

  • 我会使用flask-login。如果有帮助,我有一个使用flaskflask-loginflask-pymongo github.com/chriswilson1982/flask-mongo-app 的基本模板应用程序
  • 感谢这个模板,我正在使用它!
  • 我添加了一个摘要作为答案。我希望你觉得这个模板很有用。

标签: python mongodb authentication flask pymongo


【解决方案1】:

您可以为此使用flask-login 模块。它处理用户身份验证,允许使用 @login_required 装饰器保护路由。

我建议阅读documentation,因为您需要提供具有某些属性的类来表示您的用户,并且您需要实现一个基于给定标识符返回用户的方法。

当用户登录时,模板可以访问current_user 变量及其属性(由您定义;姓名、电子邮件等)。

这是一个简单的python代码示例(我没有包含静态文件或模板)。

from flask import Flask, render_template, request, url_for, request, redirect, abort
from flask_login import LoginManager, login_user, logout_user, login_required, current_user
from flask_pymongo import PyMongo
from flask_bcrypt import Bcrypt
from urllib.parse import urlparse, urljoin
import sys

# Import User classes
from user import User, Anonymous

# Create app
app = Flask(__name__)

# Configuration
app.config['MONGO_DBNAME'] = 'database_name'
app.config['MONGO_URI'] = 'mongo_database_uri'
app.secret_key = 'change this before production'

# Create Pymongo
mongo = PyMongo(app)

# Create Bcrypt
bc = Bcrypt(app)

# Create login manager
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.anonymous_user = Anonymous
login_manager.login_view = "login"


# ROUTES

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


@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        if current_user.is_authenticated:
            return redirect(url_for('/index'))
        return render_template('login.html')
    users = mongo.db.users
    user_data = users.find_one({'email': request.form['email']}, {'_id' : 0 })
    if user_data:
        if bc.check_password_hash(user_data['password'], request.form['pass']):
            user = User(user_data['title'], user_data['first_name'], user_data['last_name'], user_data['email'], user_data['password'], user_data['id'])
            login_user(user)

            #Check for next argument (direct user to protected page they wanted)
            next = request.args.get('next')
            if not is_safe_url(next):
                return abort(400)

            return redirect(next or url_for('profile'))

    return 'Invalid email or password'


@app.route('/register', methods=['POST', 'GET'])
def register():
    if request.method == 'POST':
        users = mongo.db.users
        existing_user = users.find_one({'email' : request.form['email']}, {'_id' : 0 })

        if existing_user is None:
            logout_user()
            hashpass = bc.generate_password_hash(request.form['pass']).decode('utf-8')
            new_user = User(request.form['title'], request.form['first_name'], request.form['last_name'], request.form['email'], hashpass)
            login_user(new_user)
            users.insert_one(new_user.dict())
            return redirect(url_for('profile'))

        return 'That email already exists!'

    return render_template('register.html')


@app.route('/profile', methods=['GET'])
@login_required
def profile():
    return render_template('profile.html')


@app.route('/list', methods=['GET'])
@login_required
def list():
    #if current_user.id:
    log(current_user.is_authenticated)
    all_users = mongo.db.users.find({}, {'_id' : 0 })
    return render_template('list.html', users = all_users)


@app.route('/logout', methods=['GET'])
@login_required
def logout():
    logout_user()
    return redirect(url_for('index'))


# Login Manager requirements

@login_manager.user_loader
def load_user(userid):
    # Return user object or none
    users = mongo.db.users
    user = users.find_one({'id': userid}, {'_id' : 0 })
    if user:
        log(user)
        return User(user['title'], user['first_name'], user['last_name'], user['email'], user['password'], user['id'])
    return None


# Safe URL
def is_safe_url(target):
    ref_url = urlparse(request.host_url)
    test_url = urlparse(urljoin(request.host_url, target))
    return test_url.scheme in ('http', 'https') and \
           ref_url.netloc == test_url.netloc


# Run app
if __name__ == '__main__':
    app.run(debug=True)

我有一个使用flaskflask-loginflask-pymongo https://github.com/chriswilson1982/flask-mongo-app 的基本模板应用程序

【讨论】:

    猜你喜欢
    • 2019-02-10
    • 2021-07-23
    • 2019-08-13
    • 2019-09-29
    • 2019-09-13
    • 1970-01-01
    • 2023-03-28
    • 2014-02-25
    • 2022-11-16
    相关资源
    最近更新 更多