使用蝗虫时如何登录Flask App [英] How to login to Flask App when using Locust

查看:100
本文介绍了使用蝗虫时如何登录Flask App的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

第一次使用蝗虫.我有一个Flask应用,该应用要求用户登录才能访问大多数路线. 我无法让Locust成功登录我的Flask应用.

First time using Locust. I have a Flask App that requires user to login to access most routes. I cant get Locust to successfully login to my Flask App.

这是我的Locust.py文件:

Here is my Locust.py file:

from locust import HttpLocust, TaskSet, task
import re


class UserBehavior(TaskSet):
    def on_start(self):
        """ on_start is called when a Locust start before any task is scheduled """
        self.client.verify = False
        self.get_token()
        self.login()

    def on_stop(self):
        """ on_stop is called when the TaskSet is stopping """
        self.logout()

    def get_token(self):
        response = self.client.get("/login")
        # Sample string from response:
        # <input id="csrf_token" name="csrf_token" type="hidden" value="REDACTED">
        self.csrftoken = re.search(' name="csrf_token" .* value="(.+?)"', response.text).group(1)
        print(f"DEBUG: self.csrftoken = {self.csrftoken}")

    def login(self):
        response = self.client.post("/login",
                                    {"email": "REDACTED", "password": "REDACTED"},
                                    headers={"X-CSRFToken": self.csrftoken})
        print(f"DEBUG: login response.status_code = {response.status_code}")

    def logout(self):
        self.client.get("/logout")

    @task(5)
    def list_domains(self):
        response = self.client.get("/domains", headers={"X-CSRFToken": self.csrftoken})
        print(f"DEBUG list: response.status_code = {response.status_code}")


class WebsiteUser(HttpLocust):
    task_set = UserBehavior
    min_wait = 5000
    max_wait = 9000

这是我的Flask应用程序的登录功能:(添加了一些调试语句)

Here is the login function of my Flask App: (with a few debug statements added)

@users.route('/login', methods=['GET', 'POST'])
def login():

    if request.method == 'POST':                                                        ##DEBUG
        logging.debug(f"debug0: inside login func with method == POST")                 ##DEBUG

    if current_user.is_authenticated:
        return redirect(url_for('main.home'))
    form = LoginForm()
    if form.validate_on_submit():
        logging.debug(f"debug0.1: inside validate_on_submit")                          ##DEBUG
        user = Users.query.filter_by(email=form.email.data).first()
        if user and user.check_password(form.password.data):
            login_user(user, remember=form.remember.data)
            next_page = request.args.get('next')
            if not next_page or url_parse(next_page).netloc != '':
                next_page = url_for('main.home')
            logging.debug(f"debug1: Login was successful")                              ##DEBUG
            return redirect(next_page)
        else:
            logging.debug(f"debug2: Login failed")                                      ##DEBUG
            flash(f'Login unsuccessful. Please check email and password!', 'danger')
    logging.debug(f"debug3: the end of login func")                                     ##DEBUG
    return render_template('login.html', title='Login', form=form)

运行蝗虫时,得到以下输出:

When i run Locust, I get this output:

[2019-09-16 18:03:06,598] Mac-mini-3.local/INFO/locust.main: Starting web monitor at *:8089
[2019-09-16 18:03:06,598] Mac-mini-3.local/INFO/locust.main: Starting Locust 0.11.0
[2019-09-16 18:03:14,069] Mac-mini-3.local/INFO/locust.runners: Hatching and swarming 2 clients at the rate 1 clients/s...
[2019-09-16 18:03:14,138] Mac-mini-3.local/ERROR/stderr: /Users/myuser/.local/share/virtualenvs/locustio-gB1-mbqd/lib/python3.7/site-packages/urllib3/connectionpool.py:851: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning)
[2019-09-16 18:03:14,162] Mac-mini-3.local/INFO/stdout: DEBUG: self.csrftoken = REDACTED
[2019-09-16 18:03:14,183] Mac-mini-3.local/INFO/stdout: DEBUG: login response.status_code = 200
[2019-09-16 18:03:14,213] Mac-mini-3.local/INFO/stdout: DEBUG list: response.status_code = 200
[2019-09-16 18:03:15,112] Mac-mini-3.local/INFO/stdout: DEBUG: self.csrftoken = REDACTED
[2019-09-16 18:03:15,137] Mac-mini-3.local/INFO/stdout: DEBUG: login response.status_code = 200

我并不担心"InsecureRequestWarning",因为这是因为我使用的是自签名证书,并且我已禁用了使用"self.client.verify = False"的验证 csrftoken看起来正确.

I'm not concerned about the 'InsecureRequestWarning' as this is because I am using a self signed cert and i have disabled verification with 'self.client.verify = False' The csrftoken looks correct.

从Flask应用程序本身中,我得到以下输出:

From the Flask App itself, I get this output:

DEBUG:user:debug0: inside login func with method == POST
INFO:flask_wtf.csrf:The CSRF token is missing.
DEBUG:user:debug3: the end of login func
DEBUG:user:debug3: the end of login func
DEBUG:user:debug3: the end of login func
DEBUG:user:debug3: the end of login func

因此,它正在使用登录功能(由debug0验证),但没有进入'form.validate_on_submit()'条件.

So, it's hitting the login function (proven by debug0) but it's not getting into the 'form.validate_on_submit()' conditional.

到目前为止,我已经花了一整天的时间,阅读文章并尝试了很多事情,例如添加X-CSRFToken标头. 我觉得我缺少一些基本知识,非常感谢您的帮助.

So far I have spent all day on this, reading articles and trying a lot of things, ie adding the X-CSRFToken headers. I feel I am missing something fundamental, and would really appreciate some help.

谢谢, WJ

推荐答案

好,我解决了这个问题,所以我想与其他任何人分享答案.正如@ user10788336所建议的,这不是蝗虫问题.

Ok, I solved it, so thought I would share the anwser for anyone else that comes across this. As suggested by @user10788336 its is not a Locust issue.

问题在于,当发布到烧瓶路径时,表单没有得到验证(即form.validate()未被设置).

The issue was that when POSTing to the flask route, the form was not being validated (ie form.validate() was not getting set).

所以,我做了两个更改.

So, I made two changes.

1)将POST更改为具有一个附加表单项,我将其称为"test-mode",并将其值设置为"locust-test"

1) changed the POST to have an additional form item which i called "test-mode" and I set the value to "locust-test"

这是新的Locust.py文件:

here is the new Locust.py file:

from locust import HttpLocust, TaskSet, task
import re

class UserBehavior(TaskSet):
    def on_start(self):
        """ on_start is called when a Locust start before any task is scheduled """
        self.client.verify = False
        self.get_token()
        self.login()

    def on_stop(self):
        """ on_stop is called when the TaskSet is stopping """
        self.logout()

    def get_token(self):
        response = self.client.get("/login")
        # Sample string from response:
        # <input id="csrf_token" name="csrf_token" type="hidden" value="REDACTED">
        self.csrftoken = re.search(' name="csrf_token" .* value="(.+?)"', response.text).group(1)
        print(f"DEBUG: self.csrftoken = {self.csrftoken}")

    def login(self):
        response = self.client.post("/login",
                                    {"email": "REDACTED",
                                     "password": "REDACTED",
                                     "test-mode": "locust-test"
                                     },
                                    headers={"X-CSRFToken": self.csrftoken})
        print(f"DEBUG: login response.status_code = {response.status_code}")

    def logout(self):
        self.client.get("/logout")

    @task(5)
    def list_domains(self):
        response = self.client.get("/domains", headers={"X-CSRFToken": self.csrftoken})
        print(f"DEBUG list: response.status_code = {response.status_code}")


class WebsiteUser(HttpLocust):
    task_set = UserBehavior
    min_wait = 5000
    max_wait = 9000

新旧之间的区别是:

<                                     {"email": "REDACTED", "password": "REDACTED"},
---
>                                     {"email": "REDACTED",
>                                      "password": "REDACTED",
>                                      "test-mode": "locust-test"
>                                      },

2)我更改了Flask应用程序的登录功能: 更改是,我不需要验证表单,因此仅在检测到我正在测试模式下运行时才跳过该表单.

2) I changed my login function the Flask app: The change is that I don't need the form to be validated, so I skip that ONLY when I detect that I am running in test-mode.

这是新的登录功能:

@users.route('/login', methods=['GET', 'POST'])
def login():

    if current_user.is_authenticated:
        return redirect(url_for('main.home'))

    form = LoginForm()

    # shortcut for Locust testing - need to avoid form.validate() (which is within form.validate_on_submit())
    form_is_ok = False
    if request.method == 'POST':
        if request.form.get('test-mode') == 'locust-test':
            form_is_ok = True
        else:
            form_is_ok = form.validate_on_submit()

    if form_is_ok:
        logging.debug(f"debug0.1: inside validate_on_submit")  # DEBUG
        user = Users.query.filter_by(email=form.email.data).first()
        if user and user.check_password(form.password.data):
            login_user(user, remember=form.remember.data)
            next_page = request.args.get('next')
            if not next_page or url_parse(next_page).netloc != '':
                next_page = url_for('main.home')
            logging.debug(f"debug1: Login was successful")  # DEBUG
            return redirect(next_page)
        else:
            logging.debug(f"debug2: Login failed")  # DEBUG
            flash(f'Login unsuccessful. Please check email and password!', 'danger')
    logging.debug(f"debug3: the end of login func")  # DEBUG
    return render_template('login.html', title='Login', form=form)

新旧之间的区别是:

<     if form.validate_on_submit():
---
>
>     # shortcut for Locust testing - need to avoid form.validate() (which is within form.validate_on_submit())
>     form_is_ok = False
>     if request.method == 'POST':
>         if request.form.get('test-mode') == 'locust-test':
>             form_is_ok = True
>         else:
>             form_is_ok = form.validate_on_submit()
>
>     if form_is_ok:

我认为这仍然是安全的……对此有何想法? 我可能会添加一个配置变量,以禁用/启用此功能.

I think this is still secure ... thoughts on that? I might add a config variable, that disables/enables this functionality.

它有效!!!

顺便说一句,蝗虫真棒!

BTW, Locust is awesome!

希望这会有所帮助.

欢呼声, WJ

这篇关于使用蝗虫时如何登录Flask App的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆