• Python Flask学习笔记之Web表单


    跨站请求伪造保护

    • Flask-WTF

    Flask-WTF能保护所有表单免受跨站请求伪造的攻击。为了实现CSRF防护,Flask-WTF需要为程序配置一个密钥。Flask-WTF使用这个密钥生成加密令牌,再用令牌验证请求中表单数据的真伪。

    • 设置密钥

    使用类来存储配置变量,项目结构清晰,同时密钥保存在环境变量中,也增强了安全性。

    touch app/config.py
    # config.py
    import os
    
    class Config(object):   
        SECRET_KEY = os.environ.get('SECRET_KEY') or 'marksecret'
    

    配置好密钥,需要在Flask读取并使用。可以在生成Flask应用之后,利用app.config.from_object()方法来完成这个操作。

    # __init__.py
    from flask import Flask
    from config import Config
    
    app = Flask(__name__)
    app.config.from_object(Config)
    
    from app import routes
    
    • 验证密钥
    >>> from app import *
    >>> app.config['SECRET_KEY']
    'marksecret'
    

    表单类

    touch app/forms.py
    # forms.py
    from flask_wtf import FlaskForm
    from wtforms import StringField, PasswordField, BooleanField, SubmitField
    from wtforms.validators import DataRequired
    
    class LoginForm(FlaskForm):
        username = StringField('username', validators=[DataRequired()])
        password = PasswordField('password', validators=[DataRequired()])
        remember_me = BooleanField('Remember Me')
        submit = SubmitField('Sign In')
    

    把表单渲染成HTML

    <!--login.html-->
    {% extends "base.html" %}
    
    {% block content %}
        <h1>Sign In</h1>
        <form action="" method="post" novalidate>
            {{ form.hidden_tag() }}
            <p>
                {{ form.username.label }}<br>
                {{ form.username(size=32) }}<br>
                {% for error in form.username.errors %}
                <span style="color: red;">[{{ error }}]</span>
                {% endfor %}
            </p>
            <p>
                {{ form.password.label }}<br>
                {{ form.password(size=32) }}
                {% for error in form.password.errors %}
                <span style="color: red;">[{{ error }}]</span>
                {% endfor %}
            </p>
            <p>{{ form.remember_me()}} {{ form.remember_me.label }}</p>
            <p>{{ form.submit() }}</p>
            
        </form> 
    {% endblock %}       }
    

    在视图函数中处理表单

    # routes.py
    from app import app
    from flask import render_template,flash,redirect,url_for
    from app.forms import LoginForm
    
    @app.route('/')
    @app.route('/user/<name>')
    def user(name):
        return '<h1>Hello, %s</h1>' % name
    
    @app.route('/index')
    def index():
        user = {'username':'mark'}
        posts = [
            {
                'author':{'username':'mark1'},
                'body':'test1'
            },
            {
                'author':{'username':'mark2'},
                'body':'test2'
            }
        ]
        return render_template('index.html',title='home',user=user,posts=posts)
    
    @app.route('/login',methods=['GET', 'POST'])
    def login():
        form = LoginForm()
        if form.validate_on_submit():
            flash('login requested for user {},remember_me={}'.format(form.username.data, form.remember_me.data))
            return redirect(url_for('index'))
        return render_template('login.html',title='sign in',form=form)
    

    重定向

    # 超链接
    <a href="/index">Home</a>
    <a href="/login">login</a>
    
    # redirect()
    return redirect('/index')
    
    # url_for()
    <a href="{{ url_for('index')}}">Home</a>
    <a href="{{ url_for('login')}}">login</a>
    
    # redirect()和url_for()
    return redirect(url_for('index'))
    

    Flash消息

    请求完成后,用户需要知道状态发生了变化。这里可以使用确认消息、警告或者错误提醒。flash()函数是向用户显示消息的有效途径。模板需要将消息渲染到基础模板中,才能让所有派生出来的模板都能显示出来。

    flash('login requested for user {},remember_me={}'.format(form.username.data, form.remember_me.data))
    # base.html
    <!DOCTYPE html>
    <html>
    <head>
        {% if title %}
        <title>{{ title }} - mark</title>
        {% else %}
        <title>welcome to mark's blog</title>
        {% endif %}
    </head>
    <body>
        <div>mark's blog 
            <a href="{{ url_for('index')}}">Home</a>
            <a href="{{ url_for('login')}}">login</a>
    
        </div>
        <hr>
        {% with messages = get_flashed_messages() %}
        {% if messages %}
        <ul>
            {% for message in messages %}
            <li>{{ message }}</li>
            {% endfor %}
        </ul>
        {% endif %}
        {% endwith %}
        {% block content %}{% endblock %}
    </body>
    </html>
    
  • 相关阅读:
    JDK的几种分析工具
    心理价值
    通过Proxool辅助数据库优化
    人生缄言
    grep 用法
    多服务器快速定位
    RandomAccessFile读取远程系统日志
    20101116 视频处理几个常用指令
    Flickr架构
    JAVA正则表达式语法
  • 原文地址:https://www.cnblogs.com/mark-zh/p/11277398.html
Copyright © 2020-2023  润新知