وبلاگ رسانگار
با ما حرفه ای باشید

سرور مجازی NVMe

اعتبار سنجی فرم فلاسک با Flask-WTF

0 9
زمان لازم برای مطالعه: 8 دقیقه


معرفی

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

تلاش برای process ورودی‌های نامعتبر کاربر می‌توانند باعث بروز باگ‌های غیرمنتظره/غیرقابل رسیدگی شوند، در صورتی که خرابی سرور نباشد. در این زمینه، اعتبارسنجی داده ها به معنای تأیید ورودی و بررسی اینکه آیا انتظارات یا معیارهای خاصی را برآورده می کند یا خیر. اعتبار سنجی داده ها قابل انجام است روی هر دو قسمت جلو و عقب

در این آموزش، روش اعتبارسنجی ورودی کاربر در فرم‌های Flask را با استفاده از Flask-WTForms افزونه.

در پایان این آموزش، فرم ثبت نام کاربر زیر را با معیارهای اعتبار سنجی خواهیم داشت:

فرم ثبت نام با اعتبار سنجی

ما از نسخه Flask استفاده خواهیم کرد 1.1.2 و Flask-WTF با نسخه 0.14.3.

برپایی

در حالی که ضروری نیست، توصیه می کنیم یک محیط مجازی ایجاد کنید تا آن را دنبال کنید:

$ mkdir flask-form-validation
$ cd flask-form-validation
$ python3 -m venv .
$ . bin/activate

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

$ pip install Flask Flask-WTF

توجه داشته باشید که اگر می خواهید از اعتبارسنجی ایمیل استفاده کنید، باید آن را نیز نصب کنید email_validator بسته (نسخه فعلی است 1.1.1):

$ pip3 install email_validator

حالا بیایید فایل های لازم خود را بسازیم. ما با ایجاد یک پایه شروع خواهیم کرد app.py، که برای سادگی، شامل برنامه، مسیرها و فرم‌های Flask ما خواهد بود:

from flask import Flask, render_template

app = Flask(__name__, template_folder='.')
app.config('SECRET_KEY')='LongAndRandomSecretKey'

ما یک شی Flask ایجاد کردیم و تنظیم کردیم template_folder به پوشه فعلی سپس ما را اختصاص دادیم Flask اعتراض به app متغیر. اضافه کردیم SECRET_KEY به ما app پیکربندی شی

این SECRET_KEY معمولاً برای رمزگذاری با اتصالات پایگاه داده و جلسات مرورگر استفاده می شود. WTForms از SECRET_KEY به عنوان نمک برای ایجاد یک توکن CSRF. می توانید در مورد CSRF بیشتر بخوانید روی این ویکی page.

اگر برنامه شما قبلاً از SECRET_KEY پیکربندی برای مقاصد دیگر، شما می خواهید یک مورد جدید برای WTForms ایجاد کنید. در این صورت می توانید تنظیم کنید WTF_CSRF_SECRET_KEY پیکربندی

بیایید یک فرم ایجاد کنیم و به جریان خود اضافه کنیم app.py:

from flask import Flask, render_template
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField

class GreetUserForm(FlaskForm):
    username = StringField(label=('Enter Your Name:'))
    submit = SubmitField(label=('Submit'))


ساده ما GreetUserForm کلاس شامل a StringField. همانطور که از نام آن پیداست، این فیلد انتظار دارد و مقدار رشته ای را برمی گرداند (همیشه می توانید آن ورودی را در صورت نیاز به انواع داده های دیگر تبدیل کنید). نام رشته است username، و از این نام برای دسترسی به داده های عنصر فرم استفاده می کنیم.

این label پارامترها چیزی هستند که ارائه خواهند شد روی ما page به طوری که کاربران متوجه شوند که یک عنصر فرم چه داده هایی را جمع آوری می کند. ما همچنین یک submit دکمه، که سعی می کند در صورتی که همه فیلدها معیارهای اعتبارسنجی ما را تأیید کنند، فرم را ارسال کند.

اکنون که راه اندازی شدیم، بیایید از WTForms برای اعتبارسنجی داده های خود استفاده کنیم!

اعتبار سنجی فرم فلاسک با Flask-WTForms

بیایید با ایجاد مسیری برای نمایش و شروع کنیم process فرم ما:



@app.route('/', methods=('GET', 'POST'))
def index():
    form = GreetUserForm()
    if form.validate_on_submit():
        return f'''<h1> Welcome {form.username.data} </h1>'''
    return render_template('index.html', form=form)

مسیر ما دارد GET و POST مواد و روش ها. این GET متد فرم را نمایش می دهد، در حالی که POST متد داده های فرم را پردازش می کند روی ارسال. ما مسیر URL را به /، یا root URL، بنابراین به عنوان صفحه اصلی برنامه وب ما ظاهر می شود page. ما رندر می کنیم index.html قالب و پاس کنید form شی به عنوان یک پارامتر

بیایید مکث کنیم و به این خط توجه کنیم: if form.validate_on_submit():. این قانون می گوید اگر روش درخواست باشد پست و اگر فیلد(های) فرم معتبر هستند، ادامه دهید. اگر ورودی فرم ما از معیارهای اعتبارسنجی ما عبور کند، روی بعدی page یک پیام خوشامدگویی ساده با نام کاربر ارائه می شود. توجه داشته باشید که در اینجا از نام فیلد (username) برای دسترسی به داده های ورودی.

برای دیدن فرم باید فرم را ایجاد کنیم index.html قالب. فایل را ایجاد کنید و کد زیر را به آن اضافه کنید:

<form method="POST" action="">
    <div class="form-row">
        <div class="form-group col-md-6">
            {{ form.csrf_token() }}
            <label for=""> {{ form.username.label }}</label>
            {{ form.username }}
        </div>
        <div class="form-group">
            {{ form.submit(class="btn btn-primary")}}
        </div>
    </div>
</form>

ما از خود استفاده می کنیم form شیء برای ارسال عناصر WTform به آن جینجا2 – تجزیه کننده قالب برای Flask.

توجه داشته باشید: csrf_token به طور خودکار توسط WTForms تولید می شود و هر بار تغییر می کند page ارائه شده است. این به ما کمک می کند تا از سایت خود در برابر حملات CSRF محافظت کنیم. به طور پیش فرض، یک فیلد مخفی است. شما همچنین می توانید استفاده کنید {{ form.hidden_field() }} برای رندر کردن تمام فیلدهای پنهان، از جمله توکن CSRF، اما توصیه نمی شود.

حالا بریم سراغ خودمون terminal برای شروع برنامه Flask ما با تایپ کردن:

$ FLASK_ENV=development flask run

برای راحتی، ما تنظیم می کنیم FLASK_ENV متغیر محیطی به “توسعه” در حین توسعه. این به برنامه اجازه می‌دهد هر بار که ذخیره را فشار می‌دهیم، مجدداً بارگذاری شود. برای ویندوز ممکن است مجبور شوید استفاده کنید set FLASK_ENV=development به شما terminal/console قبل از اجرای برنامه فلاسک

در اینجا چیزی است که اگر به آن بروید خواهیم دید localhost:

اجرای برنامه Flask با فرم

در قسمت ورودی یک نام تایپ کنید و فرم را ارسال کنید. پیام تبریکی را که ما در مسیر خود تعریف کردیم را مشاهده خواهید کرد:

ارسال فرم با نام کاربری با موفقیت انجام شد

همانطور که انتظار می رود کار می کند. اما اگر چیزی در فیلد ورودی تایپ نکردیم چه؟ همچنان فرم را تأیید می کند:

ارسال فرم بدون نام با موفقیت انجام شد

بیایید از این اتفاق جلوگیری کنیم و فقط به کاربرانی که نام خود را تایپ کرده‌اند اجازه دهیم موارد بعدی را ببینند page. برای انجام این کار، ما باید اطمینان حاصل کنیم که ما username فیلد داده ورودی دارد.

خوب import یکی از روش های داخلی اعتبارسنجی WTForms: DataRequired() از جانب wtforms.validators و آن را به ما منتقل کنید username رشته.


from wtforms.validators import ValidationError, DataRequired

class GreetUserForm(FlaskForm):
    username = StringField(label=('Enter Your Name:'),
                           validators=(DataRequired()))
    submit = SubmitField(label=('Submit'))


توجه داشته باشید که ما در حال عبور از validators پارامتر به عنوان یک لیست این به ما می گوید که می توانیم برای هر فیلد چند اعتبار سنجی داشته باشیم.

حالا که استفاده می کنیم DataRequired()، username اگر داده‌های ورودی وجود نداشته باشد، فیلد تأیید نمی‌شود:

وقتی داده‌های فرم خالی است، راهنمای ابزار به کاربر نمایش داده می‌شود

در واقع، اگر ما روی عنصر فرم کلیک راست کرده و آن را بررسی کنیم، خواهیم دید که WTForms به طور خودکار required ویژگی به فیلد ورودی:

بررسی HTML فرم برای دیدن ویژگی "الزامی" فیلد ورودی

با انجام این کار، WTForms یک اعتبار سنجی اولیه front-end را به فیلد فرم ما اضافه می کند. شما نمی توانید آن فرم را بدون آن ارسال کنید username حتی اگر سعی کنید فرم را با استفاده از ابزارهایی مانند cURL یا Postman پست کنید.

حال، فرض کنید می‌خواهیم یک قانون اعتبارسنجی جدید تنظیم کنیم که فقط به نام‌هایی اجازه می‌دهد که حداقل 5 کاراکتر داشته باشند. ما می توانیم استفاده کنیم Length() تایید کننده با min پارامتر:


from wtforms.validators import ValidationError, DataRequired, Length

class GreetUserForm(FlaskForm):
    username = StringField(label=('Enter Your Name:'), 
        validators=(DataRequired(), Length(min=5)))
    submit = SubmitField(label=('Submit'))


اگر بخواهیم فرمی را با داده های ورودی کمتر از 5 کاراکتر ارسال کنیم، معیارهای اعتبارسنجی برآورده نخواهد شد و ارسال ناموفق خواهد بود:

اعتبارسنجی wtforms ناموفق است

کلیک کردن روی دکمه ارسال هیچ کاری برای داده های نامعتبر انجام نمی دهد، همچنین هیچ خطایی را به کاربر نمایش نمی دهد. ما باید پیام های خطا را ارائه کنیم تا کاربر بفهمد چه اتفاقی می افتد روی و چگونه باید این را تعمیر کنیم.

در ما index.html الگو، درست در زیر {{ form.username }}، حلقه for-loop Jinja2 زیر را برای نمایش خطاها اضافه کنید:

 {% for field, errors in form.errors.items() %}
    <small class="form-text text-muted ">
        {{ ', '.join(errors) }}
    </small>
{% endfor %}

فرم ما اکنون می تواند خطاهای اعتبارسنجی تمیز را ارائه دهد:

خطاهای رندر فرم برای یک نام کاربری کوتاه

به هر دلیلی، اگر بخواهیم حداکثر طول داده‌های فیلد خود را محدود کنیم، می‌توانیم این کار را با عبور دادن انجام دهیم max پارامتر به Length() تایید کننده همچنین می توان پیام خطا را با ارسال یک پیام اختیاری سفارشی کرد message پارامتر با یک رشته خطای سفارشی.

بیایید به روز رسانی کنیم username فیلد بر این اساس:



class GreetUserForm(FlaskForm):
    username = StringField(label=('Enter Your Name:'),
        validators=(DataRequired(), 
        Length(min=5, max=64, message='Name length must be between %(min)d and %(max)dcharacters') ))
    submit = SubmitField(label=('Submit'))


خطاهای رندر فرم برای یک نام کاربری کوتاه با یک پیام سفارشی

بیشتر فیلدهای WTForms و اعتبار سنجی با فرم ثبت نام کاربر

فرم فعلی ما یک فیلد واحد دارد که به نوعی کسل کننده است. WTForms معیارهای گسترده اعتبار سنجی فرم و انواع فیلدهای فرم را ارائه می دهد، بنابراین بیایید از آن استفاده کنیم و چیزی با استفاده عملی ایجاد کنیم.

ما یک فرم ثبت نام کاربر ایجاد می کنیم و از اعتبار سنجی WTForms داخلی استفاده می کنیم.

ما استفاده خواهیم کرد DataRequired() اعتباردهنده فیلدهایی که می‌خواهیم مطمئن شویم کاربر آنها را پر می‌کند. حداقل و حداکثر طول فیلدها را بررسی می‌کنیم. Length() اعتبار سنجی، اعتبارسنجی ایمیل ها با Email() اعتبار سنجی و بررسی کنید که آیا دو فیلد دارای داده های یکسانی هستند EqualTo() تایید کننده

را حذف کنید GreetUserForm کلاس و شروع کد خود را با فرم جدید ما جایگزین کنید:

from flask import Flask, render_template
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, \
    SubmitField
from wtforms.validators import ValidationError, DataRequired, \
    Email, EqualTo, Length

class CreateUserForm(FlaskForm):
    username = StringField(label=('Username'), 
        validators=(DataRequired(), 
        Length(max=64)))
    email = StringField(label=('Email'), 
        validators=(DataRequired(), 
        Email(), 
        Length(max=120)))
    password = PasswordField(label=('Password'), 
        validators=(DataRequired(), 
        Length(min=8, message='Password should be at least %(min)d characters long')))
    confirm_password = PasswordField(
        label=('Confirm Password'), 
        validators=(DataRequired(message='*Required'),
        EqualTo('password', message='Both password fields must be equal!')))

    receive_emails = BooleanField(label=('Receive marketing emails.'))

    submit = SubmitField(label=('Submit'))


ما چهار زمینه مختلف در فرم های خود داریم. آخرین مورد یک دکمه ارسال معمولی است. ما با استفاده از StringField برای دریافت ورودی رشته از کاربران، مانند username و email. از سوی دیگر، PasswordField متن رمز عبور را پنهان می کند روی قسمت جلویی BooleanField به عنوان یک چک باکس ارائه می شود روی جلویی چون فقط حاوی مقادیر True (بررسی شده) یا False (بررسی نشده) است.

باید اصلاح کنیم index.html الگویی برای ارائه فیلدهای فرم جدید ما:

<div class="container">
    <h2>Registration Form</h2>
    {% for field, errors in form.errors.items() %}
    {{ ', '.join(errors) }}
    {% endfor %}
    <form class="form-horizontal" method="POST" action="">
        {{ form.csrf_token() }}
        <div class="form-group">
            {{ form.username.label }}
            {{ form.username(class="form-control") }}
        </div>
        <div class="form-group">
            {{ form.email.label }}
            {{ form.email(class="form-control") }}
        </div>
        <div class="form-group">
            {{ form.password.label }}
            {{ form.password(class="form-control") }}
        </div>
        <div class="form-group">
            {{ form.confirm_password.label }}
            {{ form.confirm_password(class="form-control") }}
        </div>
        <div class="form-group">
            {{ form.receive_emails.label }}
        </div>
        <div class="form-group">
            {{ form.submit(class="btn btn-primary")}}
        </div>
    </form>
</div>

همانطور که می بینید، فیلدهای فرم ما به درستی ارائه شده اند:

فرم ثبت نام کاربر به درستی ارائه می شود

توجه داشته باشید: اگر قرار است وب سایت شما چندین فرم مختلف داشته باشد، ممکن است بخواهید به جای تایپ هر فیلد فرم یکی یکی از ماکروهای Jinja2 استفاده کنید. استفاده از ماکروها از حوصله این مقاله خارج است، اما فرآیند ایجاد فرم را تا حد زیادی سرعت می بخشد.

ایجاد اعتبارسنجی سفارشی خود

در اکثر وب سایت ها، کاراکترهای خاصی در نام کاربری مجاز نیستند. این می تواند برای اهداف امنیتی باشد، می تواند برای لوازم آرایشی باشد. WTForms به طور پیش فرض چنین منطقی را ندارد، اما ما خودمان می توانیم آن را تعریف کنیم.

WTForms به ما اجازه می دهد تا با افزودن اعتبارسنجی، اعتبار سنجی سفارشی را اضافه کنیم روش به ما UserRegistrationForm کلاس بیایید اعتبار سفارشی را با اضافه کردن آن در فرم خود پیاده سازی کنیم validate_username() روش درست زیر submit دکمه.



class UserRegistrationForm(FlaskForm):
    
    submit = SubmitField(label=('Submit'))

    def validate_username(self, username):
        excluded_chars = " *?!'^+%&/()=})({$#"
        for char in self.username.data:
            if char in excluded_chars:
                raise ValidationError(
                    f"Character {char} is not allowed in username.")
                

ما می‌توانیم به تعداد یا چند روش اعتبارسنجی که دوست داریم اضافه کنیم. WTForms پس از تعریف، روش های اعتبارسنجی را به طور خودکار اجرا می کند.

این ValidationError class راه مناسبی برای تعریف پیام اعتبارسنجی سفارشی به ما می دهد. توجه داشته باشید که نیاز خواهید داشت import آن را از wtforms.validators قبل از استفاده از آن

بیایید این روش جدید را با وارد کردن داده‌های مناسب در همه فیلدها به جز در آزمایش کنیم username فیلد، که حاوی یک کاراکتر حذف شده – ‘%’ است.

به دلیل اعتبارسنجی سفارشی ما، فرم کاربر تأیید نمی شود

همانطور که می بینید، روش اعتبارسنجی سفارشی ما به خوبی اجرا می شود و یک خطای اعتبار سنجی تمیز را به ما ارائه می دهد، که به ما کمک می کند تا بفهمیم چه چیزی با داده های ورودی ما اشتباه است. انجام این کار تجربه کاربر را تا حد زیادی بهبود می بخشد.

می توانید از کتابخانه های خارجی، پایگاه داده یا API ها برای ترکیب با WTForms و اعتبارسنجی داده های ورودی استفاده کنید. وقتی می خواهید عکس بگیرید {{ form.some_field.data }} و در پایگاه داده بنویسید یا از آن درخواست کنید، از اعتبار سنجی WTForms برای اطمینان از ایمن بودن ذخیره آن استفاده کنید.

توجه داشته باشید: ما اکثر کدهای HTML را حذف کرده ایم زیرا مستقیماً با آموزش ما مرتبط نیستند. کد کامل در دسترس خواهد بود روی این مخزن GitHub، در صورتی که می خواهید بررسی کنید.

نتیجه

اعتبارسنجی داده ها یکی از ضروری ترین بخش های برنامه های وب Flask است. Flask-WTforms روش های بسیار قدرتمند و یادگیری آسانی را برای مدیریت داده های فرم ارائه می دهد.

اکنون که اصول اعتبارسنجی داده ها با Flask-WTF را می دانید، می توانید ادامه دهید و منطق اعتبارسنجی خود را اعمال کنید و/یا روش های خود را برای امنیت و تجربه کاربری بهتر پیاده سازی کنید.

(برچسب‌ها به ترجمه)# python



منتشر شده در 1403-01-14 18:36:03

امتیاز شما به این مطلب
دیدگاه شما در خصوص مطلب چیست ؟

آدرس ایمیل شما منتشر نخواهد شد.

لطفا دیدگاه خود را با احترام به دیدگاه های دیگران و با توجه به محتوای مطلب درج کنید