nginx Bad Request|未找到CSRF令牌| flask WTF的CSRF处理

m2xkgtsf  于 2023-11-17  发布在  Nginx
关注(0)|答案(3)|浏览(186)

问题
我为几个简单的志愿者组织工作,帮助管理和运行活动,但我们需要一个系统来跟踪人们的工作时间,以获得酬金和生产力跟踪。我认为这将是一个学习网络开发的好机会,并开始使用flask应用程序,因为它显然比django更简单,我不知道JavaScript。部署应用程序修复bug等,但是现在有人在提交登录表单后用this picture登录后回来了。
“缺少错误的请求CSRF令牌”。
“错误的请求CSRF令牌不匹配”。
“错误的请求CSRF令牌已过期”。
这些是我设法得到的错误消息,除非我实施错误,否则没有在线解决方案可以为我修复它们。我甚至没有在我的gunicorn日志中得到错误消息,我只是加载了那个图像。
经过这么长时间的调试,让它工作并自豪地展示它,现在它做到了这一点,所以也许是那些有偏见的挫折眼镜阻止了我明智地找到解决方案
代码
我有我的隐藏标记的地方,所以csrf不应该错过/webapp/website/templates/login.html

<body>
    {%extends 'base.html'%}
    {% block content %}
    <div class="shadow p-3 mb-5 bg-body rounded">
    <h3 align="center">Login</h3>
    <form method="POST">
        {{ form.hidden_tag() }}
        
        {{ form.email.label(class='form-label')}}
        {{ form.email(class='form-control')}}
        <br/>
        {{ form.password.label(class='form-label')}}
        {{ form.password(class='form-control')}}
        <br/>
        {{ form.submit(class='btn btn-danger')}}
    </form>
    </div>
    {% endblock %}
</body>
</html>

字符串
.env

SECRET_KEY='iremovedtheactualone'
DEV_DATABASE_URI='mysql+pymysql://root:root@localhost/main'
PROD_DATABASE_URI='mysql+pymysql://user:password@ip/db'
SERVER_NAME='websitename.com'


www到非www的nginx重定向不工作,我的应用程序在www上不工作是一个完全不同的问题,我的一个朋友概述了here
/webapp/website/config.py

from os import environ, path
from dotenv import load_dotenv

DB_NAME = "main"

class Config:
    """Base config."""
    #SESSION_COOKIE_NAME = environ.get('SESSION_COOKIE_NAME')
    MAX_CONTENT_LENGTH = 16*1000*1000
    RECEIPT_FOLDER = '..\\assets\\receipts'
    UPLOAD_EXTENSIONS = ['.jpg', '.png', '.pdf']
    STATIC_FOLDER = 'static'
    TEMPLATES_FOLDER = 'templates'
    SESSION_COOKIE_SECURE = True

class ProdConfig(Config):
    basedir = path.abspath(path.dirname(__file__))
    load_dotenv('/home/sai/.env')
    env_dict = dict(environ)
    FLASK_ENV = 'production'
    DEBUG = False
    TESTING = False
    SQLALCHEMY_DATABASE_URI = environ.get('PROD_DATABASE_URI')
    SECRET_KEY = environ.get('SECRET_KEY')
    SERVER_NAME = environ.get('SERVER_NAME')
    ...


/webapp/website.__init__.py

def create_app(name):
    #Flask Instance
    app = Flask(__name__)
    app.config.from_object(config.ProdConfig)

    if name  != '__main__':
        gunicorn_logger=logging.getLogger('gunicorn.error')
        app.logger.handlers = gunicorn_logger.handlers
        app.logger.setLevel(gunicorn_logger.level)

    db.init_app(app)
    migrate.init_app(app, db)
    csrf.init_app(app)
    ...


/webapp/website.auth.py

@auth.route('/login', methods=['GET', 'POST'])
def login():
    current_app.logger.info('enter login')
    ...
    if form.validate_on_submit():
        current_app.logger.info('enter submit')
        ...
        user = Users.query.filter_by(email=email).first()
        if user:
            current_app.logger.info('enter user')
            if check_password_hash(user.password_hash, password):
                current_app.logger.info('enter password')

                flash('Logged in successfully!', category='success')
                login_user(user, remember=True)
                form.email.data = ''
                form.password.data = ''
                
                #Default
                return redirect('/shift_add')

                # Method Two
                next = request.args.get('next')
                #current_app.logger.info(next)
                #if not is_safe_url(next):
                #    return abort(400)
                #else:
                #    return redirect(next or url_for('views.home'))

                # Method Three
                #next_url = request.form.get("next")
                #if next_url:
                #    return redirect(next_url)
                #return redirect(url_for('views.home') or next)

                # Method Four
                # return redirect(str(request.args.get("next")) or "/shift_add")
            else:
                ...
        else:
            ...

        ...
    else:
        current_app.logger.info('errors: ')
        current_app.logger.info(form.errors)

    return render_template('/user/login.html', form=form)

主要问题

我如何解决CSRF有时丢失或过期或不匹配的问题。这些错误都不会在我的日志中引发任何问题,除非我没有正确显示,但我不知道为什么每个错误都会发生。现在我的Chrome浏览器给我令牌丢失,Firefox给我过期,iPhone上的Safari给我不匹配。
同样令人信服的是,我如何配置CSRF错误?我错过了什么?我想学习的不仅仅是如何解决这些问题,而是为什么它们会发生,以及前进的最佳实践。谢谢!

尝试解决方案

Clearing cookies解决CSRF令牌不匹配。我尝试在Chrome上以隐身模式运行网站,我得到的CSRF令牌丢失,这是我的Chrome问题。Firefox(我的问题是它说过期),但在隐身模式下也说令牌丢失。
Apparently a bug in webkit browsers我没有运行Docker,也许这个解决方案只是超出了我的理解范围。
Too large of info being sent through不是这种情况,因为我以前成功登录过,我没有发送任何这么大的东西。

mwecs4sa

mwecs4sa1#

This答案救了我的命,我发现它只在这里经过几天的研究。

cvxl0en2

cvxl0en22#

你总是可以使用csrf_exempt装饰器。
这不是一个好的做法,

nwlqm0z1

nwlqm0z13#

当我在Gunicorn上启用多个worker时,我开始得到错误The CSRF token is invalid。我认为对我来说,问题是我的SECRET_KEY在每个worker中随机生成。所以CSRF只有在我的请求由同一个worker处理时才有效。定义一个非随机的SECRET_KEY对我来说很有效。

相关问题