python - How can i control multiple logins(like admin login and normal login) with flask login_required decorator
问题描述
I want to control multiple logins with login_required decorator in flask. In my project i want only admin to be able to add articles, and registered users to be able to comment them. I hid the logout page and profile page from unregistered users but i cant hide the add article page from registered users how can i solve this problem?
from flask import Flask,render_template,flash,redirect,url_for,session,logging,request
from flask_mysqldb import MySQL
from wtforms import Form,StringField,TextAreaField,PasswordField,validators
import email_validator
from passlib.hash import pbkdf2_sha256
from functools import wraps
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if "logged_in" in session:
return f(*args, **kwargs)
else:
flash("Bu Sayfayı Görüntülemek İçin Giriş Yapmalısınız","danger")
return redirect(location=(url_for("login")))
return decorated_function
@app.before_request
def before_request_func():
class RegisterForm(Form):
name = StringField("İsim Soyisim", validators=[validators.Length(min=4,message="En az 4 karakter uzunluğunda bir girdi giriniz"),validators.DataRequired()])
user_name = StringField("Kullanıcı Adı", validators=[validators.Length(min=4,message="En az 4 karakter uzunluğunda bir girdi giriniz"),validators.DataRequired()])
email = StringField("Email Adresi", validators=[validators.Length(min=4,message="En az 4 karakter uzunluğunda bir girdi giriniz"),validators.DataRequired(),validators.Email(message="Lütfen Geçerli Bir Email Giriniz")])
password = PasswordField("Şifre",validators=[validators.DataRequired("Lütfen Bir Parola Belirleyin"),validators.EqualTo(fieldname="confirm",message="Parolanız Uyuşmuyor")])
confirm = PasswordField("Parola Doğrula")
class LoginForm(Form):
email = StringField("Email Adresi",validators=[validators.DataRequired(message="Lütfen Emailinizi Giriniz")])
password = PasswordField("Şifre",validators=[validators.DataRequired(message="Lütfen Şifrenizi Giriniz")])
app = Flask(__name__)
mysql = MySQL(app)
app.secret_key = "furkanselek"
app.config["MYSQL_DATABASE_HOST"] = "localhost"
app.config["MYSQL_DATABASE_USER"] = "root"
app.config["MYSQL_DATABASE_PASSWORD"] = ""
app.config["MYSQL_DB"] = "furkanselek"
app.config['MYSQL_CURSORCLASS'] = "DictCursor"
app.config["MYSQL_DATABASE_PORT"] = "3306"
@app.route("/")
def index():
return render_template("index.html")
@app.route("/about")
def about():
return render_template("about.html")
@app.route("/register",methods=["GET","POST"])
def register():
form = RegisterForm(request.form)
if request.method == "POST" and form.validate():
name = form.name.data
username = form.user_name.data
email = form.email.data
password = pbkdf2_sha256.encrypt(form.password.data)
cursor = mysql.connection.cursor()
sorgu = ("Insert into users (name,email,username,password) VALUES(%s,%s,%s,%s)")
cursor.execute(sorgu,(name,email,username,password))
mysql.connection.commit()
cursor.close()
flash("Başarıyla Kayıt Oldunuz",category="warning")
return redirect(location =(url_for("login")))
else:
return render_template("register.html",form= form)
@app.route("/login",methods=["GET","POST"])
def login():
form = LoginForm(request.form)
if request.method == "POST" and form.validate():
email = form.email.data
password_entered = form.password.data
cursor = mysql.connection.cursor()
query = ("SELECT * FROM users WHERE email = %s")
result = cursor.execute(query,(email,))
if result > 0:
data = cursor.fetchone()
username = data["username"]
password = data["password"]
if pbkdf2_sha256.verify(password_entered,password):
flash("Başarıyla Giriş Yaptınız",category="warning")
if username == "maxkonrad":
session["admin"] = True
session["logged_in"] = True
session["username"] = username
return redirect(location=(url_for("index")))
else:
session["logged_in"] = True
session["username"] = username
return redirect(location=(url_for("index")))
else:
flash("Parolanızı Yanlış Girdiniz",category="warning")
return redirect(location=(url_for("login")))
else:
flash("Bu Email ile Kayıt Olmuş Bir Kullanıcı Yok")
return redirect(location=(url_for("login")))
else:
return render_template("login.html",form= form)
@app.route("/logout")
@login_required
def logout():
session.clear()
return redirect(location=(url_for("index")))
@app.route("/addarticle",methods=["GET","POST"])
def addarticle():
return render_template("addarticle.html")
@app.route("/profile")
@login_required
def profile():
return render_template("profile.html")
if __name__ == "__main__":
app.run(debug=True)
解决方案
In Role based authorization in flask-login the accepted answer appears to be using Flask-Principal However, you can also do this with Flask-User which seems to be more actively maintained. There's a superb basic-app for Flask-User which spins up with a single app.py file. The app provides two roles (admin and manager) as well as three routes that demo the authentication and basic role based authorization that is provided by Flask-User. They are pretty self-explanatory:
# The Home page is accessible to anyone
@app.route('/')
def home_page():
# The Members page is only accessible to authenticated users
@app.route('/members')
@login_required # Use of @login_required decorator
def member_page():
# The Admin page requires an 'Admin' role.
@app.route('/admin')
@roles_required('Admin') # Use of @roles_required decorator
def admin_page():
Flask-User can also be used to do more complex forms of authorization. You can make more roles and then authorize routes to only allow users access if they have that role and/or another role. For example, you could make an admin, a teacher, and a student role. And then vary accessibility based on those roles and/or combination of roles. Here's a couple of examples:
@admin_blueprint.route('/admin/teacher_or_admin')
@roles_required(['admin', 'teacher']) # requires admin OR teacher role
def admin_teacher_or_admin():
return "You have the right roles to access this page - it requires admin OR teacher roles"
@admin_blueprint.route('/admin/teacher_and_admin')
@roles_required('admin','teacher') # requires admin AND teacher roles
def admin_teacher_and_admin():
return "You have the right roles to access this view"
@admin_blueprint.route('/admin/student')
@roles_required('student')
def admin_student():
return "You have the right roles to access this page - requires student role"
Although it's not a single file like the basic-user app above, this repo demonstrates these more advanced flask-user authorization capabilities: https://github.com/lfernandez55/3200_Final_Project_Challenge
推荐阅读
- powershell - 如何使用 Powershell 识别磁盘 Optane 或 Raid 类型?
- ios - 集合视图自动调整大小和设置重复背景
- xml - 如何使用ant替换XML文件中的一行?
- java - 给定字符串中的FirstNonRepeatingCharacter在java中使用时间复杂度O(n)
- html - HTML 5:我们可以更改默认错误消息的 css
- c++ - 如何在 C++ 中使用向量创建二维数组?
- python - 如何解决 IndexError: index (x) is out of bounds for axis 0 with size (y) in wxPython?
- java - 无法运行 Spring Boot 应用程序 - rsa.crypto.RsaSecretEncryptor 不存在
- unix - maxdepth 和 mindepth 如何与 find 命令一起使用?
- php - 如何在 Laravel 刀片视图中进行算术运算?