如何在Flask中提供临时下载URL?

Koo*_*ing 7 python authentication download session-timeout flask

目前,我的index.html文件包含

<a href="static/file.ext">Download</a>
Run Code Online (Sandbox Code Playgroud)

我想更改此设置,以便下载URL仅在特定时间内有效.例如,我将如何将其更改为

<a href="get_file?file=file.ext&token=TEMPORARYTOKEN">Download</a>
Run Code Online (Sandbox Code Playgroud)

在我的Flask文件中,我可以拥有

@app.route('/get_file')
def get_file():
    filename = request.args.get('file')
    token = request.args.get('token')
    if token is valid: # what can be done here
        return send_from_directory('static', filename)
Run Code Online (Sandbox Code Playgroud)

如何生成和处理令牌?或者我接近这个完全错误?

dis*_*oqi 6

最好的方法是使用itsdangerouspackage.json 。您可以生成一个可以持续任何时间的 URL。此外,您可以秘密地对 URL 中的任何信息进行编码。这样做的好处是不需要将时间戳处理或存储到数据库中

生成持续 30 分钟的 URL 并在令牌中对用户 ID 进行编码

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer

s = Serializer('WEBSITE_SECRET_KEY', 60*30) # 60 secs by 30 mins
token = s.dumps({'user_id': currentuser.id}).decode('utf-8') # encode user id 
Run Code Online (Sandbox Code Playgroud)

使用以下命令生成你想要的 URL

url_for('get_file', token=token)
Run Code Online (Sandbox Code Playgroud)

验证 URL

@app.route('/get_file/<token>')
def get_file(token):
    s = Serializer('WEBSITE_SECRET_KEY')
    try:
        user_id = s.loads(token)['user_id']
    except:
        return None
    user = User.query.get(user_id)

    if not user:
        flash('This is an invalid or expired URL, please generate a new one!', 'warning')
        return redirect(url_for('another_route'))

    return send_from_directory('static', filename, as_attachment=True)
Run Code Online (Sandbox Code Playgroud)


Kel*_*ila 5

有几种方法可以做到这一点。

  1. 为您的令牌生成一个 UUID,并将其与所需的到期日期时间一起存储在 db 表中。然后,当有人使用令牌调用 URL 时,您只需根据数据库检查它的有效性和到期时间。

  2. 如果您不想使用 db 来存储令牌,则可以使用 GPG 来加密包含到期日期时间的字符串,并将生成的加密字符串用作您的令牌。这意味着您的令牌将比 UUID 长很多,但您可以避免使用 db。

我建议使用 UUID 和 db 表。

  • 对于选项 2,应该使用“itsdangerous”包,而不是用 GPG 重新发明轮子,它已经是一个 Flask 依赖项,并且有专门用于此目的的方法(URL 签名)。安全性很难做到正确,人们应该总是更喜欢使用经过时间考验的经过验证和审计的库,而不是提出自己的加密/签名机制。 (4认同)