احراز هویت کاربران در Flask با Flask-Login

فهرست مطالب

“`html





احراز هویت کاربران در Flask با Flask-Login



احراز هویت کاربران در Flask با Flask-Login: راهنمای جامع

در دنیای توسعه وب، احراز هویت کاربران یکی از حیاتی‌ترین جنبه‌ها به شمار می‌رود. اطمینان از اینکه تنها کاربران مجاز به منابع محافظت‌شده دسترسی دارند، نیازمند یک سیستم احراز هویت قوی و قابل اعتماد است. فریم‌ورک Flask پایتون با ارائه انعطاف‌پذیری و سادگی، بستری مناسب برای ساخت برنامه‌های وب فراهم می‌کند. در این میان، کتابخانه Flask-Login با ارائه ابزارهای لازم، فرآیند احراز هویت را در Flask به طرز چشمگیری آسان‌تر می‌کند.

این مقاله به عنوان یک راهنمای جامع، شما را در پیاده‌سازی یک سیستم احراز هویت کامل در Flask با استفاده از Flask-Login یاری خواهد کرد. از تنظیمات اولیه و تعریف مدل‌های کاربری گرفته تا پیاده‌سازی ورود، خروج، مدیریت نشست‌ها و محافظت از مسیرها، تمامی مراحل به صورت گام به گام و با ارائه نمونه کدها توضیح داده خواهند شد. هدف ما این است که شما بتوانید پس از مطالعه این راهنما، یک سیستم احراز هویت امن و کارآمد را در برنامه Flask خود پیاده‌سازی کنید.

1. مقدمه ای بر Flask-Login و اهمیت احراز هویت

Flask-Login یک افزونه قدرتمند برای فریم‌ورک Flask است که مدیریت احراز هویت کاربران را به طرز قابل توجهی تسهیل می‌کند. این افزونه با ارائه ابزارهایی برای مدیریت نشست‌ها (Sessions)، ورود (Login)، خروج (Logout) و محافظت از مسیرها (Routes)، به توسعه‌دهندگان کمک می‌کند تا یک سیستم احراز هویت امن و کارآمد را به سرعت پیاده‌سازی کنند.

چرا احراز هویت مهم است؟

  • امنیت: احراز هویت از دسترسی غیرمجاز به اطلاعات حساس و منابع محافظت‌شده جلوگیری می‌کند.
  • اعتبار: با احراز هویت، می‌توانید هویت کاربران خود را تأیید کنید و اطمینان حاصل کنید که کاربرانی که ادعا می‌کنند، واقعاً همان افراد هستند.
  • شخصی‌سازی: با احراز هویت، می‌توانید تجربه کاربری را بر اساس هویت کاربر شخصی‌سازی کنید.
  • حسابرسی: احراز هویت به شما امکان می‌دهد فعالیت کاربران را ردیابی کنید و در صورت بروز هرگونه مشکل، مسئولیت‌ها را مشخص کنید.

بدون احراز هویت، برنامه شما در برابر طیف گسترده‌ای از حملات سایبری آسیب‌پذیر خواهد بود. هکرها می‌توانند با جعل هویت کاربران، به اطلاعات حساس دسترسی پیدا کنند، داده‌ها را دستکاری کنند یا حتی کنترل کامل برنامه شما را به دست بگیرند. بنابراین، پیاده‌سازی یک سیستم احراز هویت قوی و قابل اعتماد، برای حفظ امنیت و اعتبار برنامه شما ضروری است.

2. پیش نیازها و نصب Flask-Login

برای شروع کار با Flask-Login، ابتدا باید مطمئن شوید که پیش‌نیازهای لازم را دارید. این پیش‌نیازها عبارتند از:

  • Python: نسخه 3.6 یا بالاتر
  • Flask: نسخه 1.0 یا بالاتر

اگر Flask را نصب ندارید، می‌توانید آن را با استفاده از pip نصب کنید:

pip install Flask

پس از نصب Flask، می‌توانید Flask-Login را نیز با استفاده از pip نصب کنید:

pip install Flask-Login

علاوه بر Flask و Flask-Login، به یک پایگاه داده نیز نیاز خواهید داشت تا اطلاعات کاربران خود را ذخیره کنید. می‌توانید از پایگاه داده‌های مختلفی مانند SQLite، MySQL یا PostgreSQL استفاده کنید. در این راهنما، از SQLite به عنوان پایگاه داده استفاده خواهیم کرد، زیرا پیاده‌سازی آن ساده‌تر است.

برای کار با SQLite در Flask، به کتابخانه Flask-SQLAlchemy نیز نیاز خواهید داشت. می‌توانید آن را با استفاده از pip نصب کنید:

pip install Flask-SQLAlchemy

پس از نصب تمام پیش‌نیازها، می‌توانید به مرحله بعدی بروید و برنامه Flask خود را تنظیم کنید.

3. تنظیمات اولیه و پیکربندی Flask

در این مرحله، باید برنامه Flask خود را تنظیم کنید و Flask-Login و Flask-SQLAlchemy را پیکربندی کنید. ابتدا یک فایل پایتون به نام app.py ایجاد کنید و کدهای زیر را در آن قرار دهید:


from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_secret_key'  # کلید مخفی خود را جایگزین کنید
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'  # آدرس پایگاه داده SQLite
db = SQLAlchemy(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'  # مسیری که کاربر باید به آن هدایت شود در صورت نیاز به ورود
login_manager.login_message = "لطفا برای دسترسی به این صفحه وارد شوید." # پیام نمایش داده شده برای کاربرانی که وارد نشده اند.

from routes import * #درون ریزی Route ها

if __name__ == '__main__':
    with app.app_context():
        db.create_all()
    app.run(debug=True)

در این کد:

  • Flask، SQLAlchemy و LoginManager را از کتابخانه‌های مربوطه وارد کرده‌ایم.
  • یک شیء Flask جدید ایجاد کرده‌ایم.
  • تنظیمات مربوط به کلید مخفی (SECRET_KEY) و آدرس پایگاه داده (SQLALCHEMY_DATABASE_URI) را پیکربندی کرده‌ایم. توجه داشته باشید که باید یک کلید مخفی قوی و تصادفی را جایگزین 'your_secret_key' کنید.
  • یک شیء SQLAlchemy جدید ایجاد کرده‌ایم و آن را به برنامه Flask خود مرتبط کرده‌ایم.
  • یک شیء LoginManager جدید ایجاد کرده‌ایم و آن را به برنامه Flask خود مرتبط کرده‌ایم.
  • login_view را برای LoginManager تعیین کرده‌ایم. این مسیری است که کاربر باید به آن هدایت شود در صورتی که سعی کند به یک مسیر محافظت‌شده دسترسی پیدا کند در حالی که وارد سیستم نشده است.

توضیحات بیشتر در مورد تنظیمات:

  • SECRET_KEY: این کلید برای رمزنگاری اطلاعات نشست‌ها (Sessions) استفاده می‌شود. استفاده از یک کلید مخفی قوی و تصادفی برای حفظ امنیت برنامه شما ضروری است. می‌توانید از یک ابزار تولید رمز تصادفی برای ایجاد یک کلید مخفی قوی استفاده کنید.
  • SQLALCHEMY_DATABASE_URI: این آدرس پایگاه داده‌ای است که SQLAlchemy باید به آن متصل شود. در این مثال، از یک پایگاه داده SQLite به نام site.db استفاده می‌کنیم که در همان پوشه فایل app.py ایجاد خواهد شد.
  • login_view: این نام تابعی است که برای نمایش صفحه ورود استفاده می‌شود. Flask-Login از این نام برای هدایت کاربرانی که وارد سیستم نشده‌اند به صفحه ورود استفاده می‌کند.

در نهایت، باید پایگاه داده را ایجاد کنید. برای این کار، کافی است برنامه Flask خود را یک بار اجرا کنید. SQLAlchemy به طور خودکار پایگاه داده site.db را ایجاد خواهد کرد.

4. تعریف مدل‌های کاربری و پایگاه داده

در این مرحله، باید مدل‌های کاربری خود را تعریف کنید و پایگاه داده را ایجاد کنید. برای این کار، یک فایل پایتون به نام models.py ایجاد کنید و کدهای زیر را در آن قرار دهید:


from app import db, login_manager
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password_hash = db.Column(db.String(128))

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

    def __repr__(self):
        return f"User('{self.username}', '{self.email}')"

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

در این کد:

  • کلاس User را تعریف کرده‌ایم که از db.Model و UserMixin ارث می‌برد. db.Model یک کلاس پایه برای مدل‌های پایگاه داده در SQLAlchemy است و UserMixin یک کلاس کمکی از Flask-Login است که ویژگی‌ها و متدهای لازم برای مدیریت کاربران را فراهم می‌کند.
  • ستون‌های id، username، email و password_hash را برای مدل User تعریف کرده‌ایم.
  • متدهای set_password و check_password را برای تنظیم و بررسی رمز عبور کاربران تعریف کرده‌ایم. این متدها از کتابخانه werkzeug.security برای هش کردن و بررسی رمز عبور استفاده می‌کنند.
  • تابع load_user را تعریف کرده‌ایم که توسط Flask-Login برای بارگیری اطلاعات کاربر از پایگاه داده استفاده می‌شود. این تابع باید یک شیء User را برگرداند که با شناسه کاربری (user_id) داده شده مطابقت داشته باشد.

توضیحات بیشتر در مورد مدل کاربری:

  • UserMixin: این کلاس کمکی ویژگی‌ها و متدهای لازم برای مدیریت کاربران را فراهم می‌کند، از جمله is_authenticated، is_active و is_anonymous.
  • set_password: این متد رمز عبور کاربر را هش می‌کند و آن را در ستون password_hash ذخیره می‌کند. از تابع generate_password_hash از کتابخانه werkzeug.security برای هش کردن رمز عبور استفاده می‌شود.
  • check_password: این متد رمز عبور داده شده را با رمز عبور هش شده ذخیره شده در پایگاه داده مقایسه می‌کند. از تابع check_password_hash از کتابخانه werkzeug.security برای بررسی رمز عبور استفاده می‌شود.
  • load_user: این تابع توسط Flask-Login برای بارگیری اطلاعات کاربر از پایگاه داده استفاده می‌شود. Flask-Login از این تابع برای بارگیری اطلاعات کاربر در هر درخواست استفاده می‌کند تا بتواند تعیین کند که آیا کاربر وارد سیستم شده است یا خیر.

5. پیاده سازی ورود، خروج و ثبت نام کاربران

در این مرحله، باید منطق مربوط به ورود، خروج و ثبت نام کاربران را پیاده‌سازی کنید. برای این کار، یک فایل پایتون به نام routes.py ایجاد کنید و کدهای زیر را در آن قرار دهید:


from flask import render_template, redirect, url_for, flash, request
from app import app, db
from models import User
from flask_login import login_user, logout_user, login_required, current_user
from forms import RegistrationForm, LoginForm

@app.route('/register', methods=['GET', 'POST'])
def register():
    form = RegistrationForm()
    if form.validate_on_submit():
        user = User(username=form.username.data, email=form.email.data)
        user.set_password(form.password.data)
        db.session.add(user)
        db.session.commit()
        flash('حساب شما با موفقیت ایجاد شد! لطفا وارد شوید.', 'success')
        return redirect(url_for('login'))
    return render_template('register.html', title='ثبت نام', form=form)

@app.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('dashboard'))
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user and user.check_password(form.password.data):
            login_user(user, remember=form.remember.data)
            next_page = request.args.get('next')
            return redirect(next_page) if next_page else redirect(url_for('dashboard'))
        else:
            flash('نام کاربری یا رمز عبور اشتباه است.', 'danger')
    return render_template('login.html', title='ورود', form=form)

@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('home'))

@app.route('/dashboard')
@login_required
def dashboard():
    return render_template('dashboard.html', title='داشبورد')

@app.route('/')
def home():
    return render_template('home.html', title='خانه')

در این کد:

  • مسیرهای /register، /login، /logout و /dashboard را تعریف کرده‌ایم.
  • مسیر /register برای ثبت نام کاربران جدید استفاده می‌شود. این مسیر یک فرم ثبت نام را نمایش می‌دهد و در صورت معتبر بودن فرم، یک کاربر جدید را در پایگاه داده ایجاد می‌کند.
  • مسیر /login برای ورود کاربران استفاده می‌شود. این مسیر یک فرم ورود را نمایش می‌دهد و در صورت معتبر بودن فرم، کاربر را وارد سیستم می‌کند.
  • مسیر /logout برای خروج کاربران استفاده می‌شود. این مسیر کاربر را از سیستم خارج می‌کند و به صفحه اصلی هدایت می‌کند.
  • مسیر /dashboard یک مسیر محافظت‌شده است که فقط کاربران وارد شده می‌توانند به آن دسترسی داشته باشند. این مسیر یک صفحه داشبورد را نمایش می‌دهد.

توضیحات بیشتر در مورد مسیرها:

  • @login_required: این دکوراتور از Flask-Login برای محافظت از مسیرها استفاده می‌شود. اگر کاربر سعی کند به یک مسیر محافظت‌شده دسترسی پیدا کند در حالی که وارد سیستم نشده است، به صفحه ورود هدایت می‌شود.
  • login_user: این تابع از Flask-Login برای ورود کاربر به سیستم استفاده می‌شود. این تابع یک شیء User را به عنوان آرگومان می‌گیرد و اطلاعات کاربر را در نشست (Session) ذخیره می‌کند.
  • logout_user: این تابع از Flask-Login برای خروج کاربر از سیستم استفاده می‌شود. این تابع اطلاعات کاربر را از نشست (Session) حذف می‌کند.
  • current_user: این شیء از Flask-Login اطلاعات کاربر وارد شده را در اختیار قرار می‌دهد.

همچنین به فرم هایی برای ثبت نام و ورود نیاز دارید. یک فایل پایتون به نام forms.py ایجاد کنید و کدهای زیر را در آن قرار دهید:


from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
from models import User

class RegistrationForm(FlaskForm):
    username = StringField('نام کاربری', validators=[DataRequired(), Length(min=2, max=20)])
    email = StringField('ایمیل', validators=[DataRequired(), Email()])
    password = PasswordField('رمز عبور', validators=[DataRequired()])
    confirm_password = PasswordField('تکرار رمز عبور', validators=[DataRequired(), EqualTo('password')])
    submit = SubmitField('ثبت نام')

    def validate_username(self, username):
        user = User.query.filter_by(username=username.data).first()
        if user:
            raise ValidationError('این نام کاربری قبلا انتخاب شده است. لطفا نام کاربری دیگری انتخاب کنید.')

    def validate_email(self, email):
        user = User.query.filter_by(email=email.data).first()
        if user:
            raise ValidationError('این ایمیل قبلا ثبت شده است. لطفا ایمیل دیگری وارد کنید.')

class LoginForm(FlaskForm):
    username = StringField('نام کاربری', validators=[DataRequired(), Length(min=2, max=20)])
    password = PasswordField('رمز عبور', validators=[DataRequired()])
    remember = BooleanField('مرا به خاطر بسپار')
    submit = SubmitField('ورود')

در این کد:

  • از flask_wtf برای ایجاد فرم استفاده شده است
  • فرم ثبت نام شامل فیلد های نام کاربری، ایمیل، رمز عبور، تکرار رمز عبور و دکمه ثبت است
  • فرم ورود شامل فیلد های نام کاربری، رمز عبور، مرا به خاطر بسپار و دکمه ورود است
  • توابعی برای بررسی یکتا بودن نام کاربری و ایمیل در فرم ثبت نام تعریف شده است

6. طراحی صفحات ورود، خروج و ثبت نام

در این مرحله، باید صفحات HTML مربوط به ورود، خروج و ثبت نام را طراحی کنید. برای این کار، سه فایل HTML به نام‌های login.html، logout.html و register.html در پوشه templates ایجاد کنید و کدهای زیر را در آن‌ها قرار دهید:

login.html:


{% extends 'layout.html' %}
{% block content %}
    
{{ form.hidden_tag() }}
ورود
{{ form.username.label(class="form-control-label") }} {% if form.username.errors %} {{ form.username(class="form-control form-control-lg is-invalid") }}
{% for error in form.username.errors %} {{ error }} {% endfor %}
{% else %} {{ form.username(class="form-control form-control-lg") }} {% endif %}
{{ form.password.label(class="form-control-label") }} {% if form.password.errors %} {{ form.password(class="form-control form-control-lg is-invalid") }}
{% for error in form.password.errors %} {{ error }} {% endfor %}
{% else %} {{ form.password(class="form-control form-control-lg") }} {% endif %}
{{ form.remember(class="form-check-input") }} {{ form.remember.label(class="form-check-label") }}
{{ form.submit(class="btn btn-outline-info") }}
فراموشی رمز عبور؟
نیاز به حساب کاربری دارید؟ ثبت نام کنید
{% endblock content %}

register.html:


{% extends 'layout.html' %}
{% block content %}
    
{{ form.hidden_tag() }}
ثبت نام
{{ form.username.label(class="form-control-label") }} {% if form.username.errors %} {{ form.username(class="form-control form-control-lg is-invalid") }}
{% for error in form.username.errors %} {{ error }} {% endfor %}
{% else %} {{ form.username(class="form-control form-control-lg") }} {% endif %}
{{ form.email.label(class="form-control-label") }} {% if form.email.errors %} {{ form.email(class="form-control form-control-lg is-invalid") }}
{% for error in form.email.errors %} {{ error }} {% endfor %}
{% else %} {{ form.email(class="form-control form-control-lg") }} {% endif %}
{{ form.password.label(class="form-control-label") }} {% if form.password.errors %} {{ form.password(class="form-control form-control-lg is-invalid") }}
{% for error in form.password.errors %} {{ error }} {% endfor %}
{% else %} {{ form.password(class="form-control form-control-lg") }} {% endif %}
{{ form.confirm_password.label(class="form-control-label") }} {% if form.confirm_password.errors %} {{ form.confirm_password(class="form-control form-control-lg is-invalid") }}
{% for error in form.confirm_password.errors %} {{ error }} {% endfor %}
{% else %} {{ form.confirm_password(class="form-control form-control-lg") }} {% endif %}
{{ form.submit(class="btn btn-outline-info") }}
قبلا حساب کاربری دارید؟ وارد شوید
{% endblock content %}

layout.html:







{% if title %}
Flask Blog - {{ title }}
{% else %}
Flask Blog
{% endif %}

{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}

{{ message }}

{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}

نوار کناری

اینجا میتونید اطلاعات مفیدی رو قرار بدید

  • آخرین پست ها
  • اطلاعیه ها
  • تقویم
  • و غیره