#python #flask
Вопрос:
Я использовал flask для разработки веб-приложения. В отчете о пентестинге говорится, что если функция загрузки имеет статическую ссылку, то ссылка на загрузку не должна быть предсказуемой. Поэтому я должен изменить int в ссылке для загрузки.
HTML:
<td><a href="{{ url_for('course_chat_export_csv', group_id=g.id) }}"
target="_blank">CSV</a> |
<a href="{{ url_for('course_chat_export_excel', group_id=g.id) }}"
target="_blank">Excel</a></td>
routes.py:
@app.route('/course/download/<int:group_id>/csv', methods=['GET', 'POST'])
def export_csv(group_id):
group = Group.query.get(group_id)
file_name = str.lower(group.title) ".csv"
messages = Message.query.filter(Message.to_id == group.chat_id).order_by(Message.date.asc()).all()
temp = os.path.join(app.root_path, 'temp')
export_csv(messages, os.path.join(temp, file_name))
return send_from_directory(directory=temp, file_name=file_name, as_attachment=True,
attachment_filename=file_name)
Как я мог этого достичь?
Ответ №1:
Вы можете использовать JWT в обмен на ссылку для загрузки.
@app.route('/course/download/<str:token>/csv', methods=['GET', 'POST'])
def export_csv(token):
try:
data = jwt.decode(token, current_app.secret_key, algorithms=["HS256"])
except jwt.exceptions.InvalidTokenError:
return "invalid token", 401
group_id = data["group_id"]
group = Group.query.get(group_id)
file_name = str.lower(group.title) ".csv"
messages = Message.query.filter(Message.to_id == group.chat_id).order_by(Message.date.asc()).all()
temp = os.path.join(app.root_path, 'temp')
export_csv(messages, os.path.join(temp, file_name))
return send_from_directory(directory=temp, file_name=file_name, as_attachment=True,
attachment_filename=file_name)
Вы можете генерировать такие токены с помощью модуля jwt.
import jwt
from datetime import datetime, timedelta
JWT_EXP_DELTA_SECONDS = 20000
group_id = 25
token = jwt.encode(
{"group_id": group_id , "exp": datetime.utcnow() timedelta(seconds=JWT_EXP_DELTA_SECONDS)}, # exp is optional, but you can use it if you want the download link only to work during a certain period of time
current_app.config["INVITES_SECRET"],
algorithm="HS256",
)
В разделе данных jwt вы также можете указать идентификатор пользователя, а затем проверить, соответствует ли пользователь, который в данный момент вошел в систему, URL-адресу, который он использует для загрузки. (в случае, если у вас есть аутентификация)
Альтернативой, требующей использования базы данных, является просто изменение маркера для случайной длинной строки, а затем сохранение в базе данных связи между случайными строками и идентификаторами групп.
Конечно, работает любая зашифрованная строка; но использование JWT дает вам хорошо зарекомендовавший себя протокол, который вы можете использовать также для передачи данных group_id и даже user_id. Однако обратите внимание, что любой, у кого есть токен, сможет прочитать такие данные, поскольку сами данные не зашифрованы.
Комментарии:
1. какую версию jwt вы используете? некоторые версии не имеют метода кодирования
2. что вы подразумеваете под версией? у вас есть какая-нибудь ссылка на то, что вы упомянули? или вы имеете в виду алгоритм?