хэш int в ссылке для загрузки в колбе

#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. что вы подразумеваете под версией? у вас есть какая-нибудь ссылка на то, что вы упомянули? или вы имеете в виду алгоритм?