Код: Выделить всё
import jwt
class RegForm(FlaskForm):
email = EmailField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
password2 = PasswordField('Repeat password',
validators=[DataRequired(), EqualTo('password')])
register = SubmitField('REGISTER')
class VerForm(FlaskForm):
code = StringField('Code', validators=[DataRequired()])
verify = SubmitField('VERIFY')
def validate_code(self, code):
try:
payload = jwt.decode(session['TOKEN'],
current_app.config['SECRET_KEY'],
algorithms=['HS256'])['payload']
except jwt.exceptions.ExpiredSignatureError:
current_app.config['TRIES-LEFT'] = -1
raise ValidationError('The code has been expired.')
if code.data != payload:
raise ValidationError(f'Code mismatch. {current_app.config.get('TRIES-LEFT', 0)} tries left.')
@bp.route('/auth', methods=['GET', 'POST'])
def auth():
# Ywo forms on the single page.
reg = RegForm(prefix='reg')
ver = VerForm(prefix='ver')
if reg.register.data:
if reg.validate():
# Generate 5-digit verification code...
code = ''.join(sample('0123456789', 5))
# .. and.send it to specified email address.
send_code(reg.email.data, code)
@# Hand over hash/token for feature requests.
session['EMAIL'] = reg.email.data
session['PASSWORD-HASH'] = generate_password_hash(reg.password.data)
session['TOKEN'] = jwt.encode(
{'payload': code, 'exp': time() + 86400},
current_app.config['SECRET_KEY'],
algorithm='HS256')
# Three shots before sending another code.
current_app.config['TRIES-LEFT'] = 3
return redirect(url_for('main.auth'))
elif ver.verify.data:
if current_app.config['TRIES-LEFT']:
if ver.validate():
# Put an user into database.
user = User(email=session.pop('EMAIL'))
user.password_hash = session['PASSWORD-HASH']
db.session.add(user)
db.session.commit()
login_user(user, remember=False)
return redirect(url_for('main.index'))
else:
if current_app.config['TRIES-LEFT'] == -1:
# Code is xpired. Generate a new one and resend it.
# Mismatch or another error.
current_app.config['TRIES-LEFT'] -= 1
else:
# Three fails. Generate a new one and resend it.
current_app.config['TRIES-LEFT'] = 3
return render_template('login.html', reg=reg, ver=ver)
Отправьте код подтверждения пользователю.
Если возникнут три ошибки несоответствия, повторно отправьте новый код.
Если срок действия кода истек. , повторно отправьте новый код.
Я хотел бы уточнить некоторые аспекты.
А как насчет надежности и безопасности? достаточно ли это безопасно?
Хороша ли идея использовать объект сеанса для передачи хеша/токена между
функциями запросов/соперничеств? Не лучше ли вместо этого использовать app.config?
Нужно ли на время отключить кнопку «Отправить повторно», чтобы защитить форму от ботов?Подходят ли JSON Web Tokens для этой цели?
Кроме того, я реализовал ту же форму на основе ajax-запросов. Предпочитаю ли я последнее?
Что еще я могу сделать, чтобы улучшить свою форму?
Спасибо.
Подробнее здесь: https://stackoverflow.com/questions/793 ... t-practice