#python #flask #python-requests
Вопрос:
Я создаю приложение flask и пытаюсь отправлять запросы post в терминале с помощью requests
библиотеки, но оно выдает ошибку 400, но я не знаю, что неправильно в запросе.
Вот страница регистрации, которую я пытаюсь найти в своем браузере:
И последующий результат после отправки поста:
Однако, когда я пытаюсь воссоздать этот запрос post и использовать ту же информацию в командной строке, я получаю 400
код состояния.
Вот базовый код, который я использую для его создания:
форма:
class SignupForm(FlaskForm):
"""Main form for sign up page"""
email = EmailField(label = 'email', validators = [DataRequired(), Email()])
password = PasswordField(label = 'password',
validators = [DataRequired(), Length(min=9, max=20),
check_valid_password])
sec_question = SelectField(label = 'Security Question',
validators = [DataRequired()],
choices = ['What is your favorite band?',
'What is your favorite pets name?',
'What was the last name of your favorite childhoold teacher?',
'In what city were you born?',
'What is your best friends last name?',
'What is the country you would most like to visit?'])
sec_answer = TextField(label='your answer. not case sensitive', validators=[DataRequired(), Length(4, 200)])
Вот код колбы, который обрабатывает входящий запрос:
@user.route('/signup', methods=['GET', 'POST'])
def signup():
form = SignupForm()
if form.validate_on_submit():
user_exists = User.query.filter_by(email = request.form.get('email')).first()
if user_exists:
flash('User already exists with that e-mail. Please login instead', 'warning')
return redirect(url_for('user.signup', form = form))
user = User()
form.populate_obj(user)
user.password = User.encrypt_password(request.form.get('password'))
user.save()
# send confirmation e-mail using celery
from app.blueprints.main.tasks import send_email
token = generate_new_account_token(form.email.data)
send_email.delay(
subject = 'Welcome to CPM! Please confirm your account',
recipients = [form.email.data],
template = 'email/user_new_confirm.html',
confirm_url = url_for('user.confirm_new', token = token, _external=True)
)
flash(f'A confirmation e-mail has been sent to {form.email.data}', 'info')
redirect(url_for('user.signup', form=form))
return render_template('blueprints/user/signup.html', form=form)
Я ни за что на свете не могу заставить это работать внутри почтового запроса. Он работает localhost:5000
на моем компьютере.
Вот два примера, иллюстрирующих эту проблему. Моя успешная GET
просьба:
Моя неудачная POST
просьба:
data = {'email': 'myemail@gmail.com', 'password': 'Passw0rd!', 'sec_question': 'What is your favorite band?', 'sec_answer': 'paul simon'}
requests.post('http://localhost:5000/signup', data = data)
Комментарии:
1. Похоже, что используемый вами запрос sec_question не соответствует ни одному из вариантов. «Какая ваша любимая группа? «против» Какой ваш любимый музыкальный исполнитель?»
2. @Nickodell только что внес изменения, но результаты те же.
Ответ №1:
В качестве меры безопасности формы должны отправлять маркер CSRF вместе с запросом POST для предотвращения атак CSRF (Подделка межсайтовых запросов, иногда сокращенно XSRF). Браузеры справятся с этим за вас, но в cURL вам придется вручную извлекать и использовать токен CSRF (что обычно вызывает боль в шее).
В целях разработки вы можете временно отключить защиту CSRF. Вот объяснение того, как это сделать с помощью колбы.
По сути, просто добавьте @csrf.exempt
декоратора в свой signup
метод:
from flask_wtf import csrf
@user.route('/signup', methods=['GET', 'POST'])
@csrf.exempt
def signup():
# The rest of the method
Кроме того, вы можете быстро и легко отключить CSRF для всех ваших представлений, установив значение WTF_CSRF_CHECK_DEFAULT
False
.
ПРЕДУПРЕЖДЕНИЕ: Никогда не перемещайте представление формы в рабочую среду с отключенной защитой CSRF.