我使用 Flask 开发了一个 Web 应用程序。 在渗透测试报告中,它说,如果下载功能有一个静态链接,那么下载链接应该是不可预测的。 所以我应该更改下载链接中的 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)
我怎么能做到这一点?
答案 0 :(得分: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 的数据部分中,您还可以包含 userId,然后检查当前登录的用户是否与用于下载的 url 相对应。 (如果您有身份验证)
另一种需要使用数据库的替代方法是将令牌更改为随机长字符串,然后在数据库中存储随机字符串和组 ID 之间的关系。
当然,任何类型的加密字符串都可以;但是使用 JWT 为您提供了一个完善的协议,您可以使用它来传递 group_id 甚至 user_id 的数据。但请注意,任何拥有令牌的人都可以读取此类数据,因为数据本身并未加密。