问题陈述
我正在开发一个在表格中显示项目列表的 Flask Web 应用程序。用户可以选择一行并点击一个Delete按钮来删除该项目。然而,在从数据库中删除项目之前,用户首先被路由到确认屏幕,其中显示了一些项目详细信息以及一个Confirm按钮。确认页面的 url 遵循以下模式:dashboard/confirm-delete/<id>实际删除页面的 url 遵循以下模式:dashboard/delete/<id>。有关admin/views.py更多详细信息,请参见下文。
当系统正常工作时,我遇到的问题是用户可以通过在地址栏中键入 来跳过确认页面dashboard/delete/<id>,其中<id>由实际项目 id 代替。
问题
有没有办法阻止用户访问,dashboard/delete/<id>除非他们先去dashboard/confirm-delete/<id>(确认屏幕)?或者,我的方法是否错误,是否有更好的方法可用?
当前代码:
dashboard.html选择一行并按下删除按钮时调用我页面中的函数:
$('#remove').click(function () {
var id = getId();
window.location.href="/dashboard/confirm-delete" + $.trim(id);
});
Run Code Online (Sandbox Code Playgroud)
确认按钮confirm-delete.html(删除确认页面):
<a class="btn btn-default" href="{{ url_for('admin.delete_item', id=item.id) }}" role="button">Confirm Delete</a>
Run Code Online (Sandbox Code Playgroud)
我的admins/views.py:
@admin_blueprint.route('dashboard/confirm-delete/<id>')
@login_required
@groups_required(['admin'})
def confirm_delete_item(id)
item = Item.query.get_or_404(id)
return render_template('admin/confirm-delete.html', item=item, title="Delete Item")
@admin_blueprint.route('dashboard/delete/<id>', methods=['GET', 'POST'])
@login_required
@groups_required(['admin'})
def delete_item(id)
item = Item.query.get_or_404(id)
db.session.delete(item)
db.commit()
return redirect(url_for('home.homepage'))
Run Code Online (Sandbox Code Playgroud)
解决方案
根据标记为已接受的答案,我解决了以下问题:
首先,我创建了一个新表单来处理页面中的Submit按钮confirm-delete.html:
admin/forms.py:
from flask_wtf import FlaskForm
from wtforms import SubmitField
class DeleteForm(FlaskForm):
submit = SubmitField('Confirm')
Run Code Online (Sandbox Code Playgroud)
我将Confirm Button代码替换为以下内容confirm-delete.html:
<form method="post">
{{ form.csrf_token }}
{{ form.submit }}
</form>
Run Code Online (Sandbox Code Playgroud)
最后,我将这两个函数合并app/views.py如下:
@admin_blueprint.route('dashboard/confirm-delete/<id>', methods=['GET', 'POST'])
@login_required
@groups_required(['admin'})
def confirm_delete_item(id)
form = DeleteForm()
item = Item.query.get_or_404(id)
if form.validate_on_submit():
if form.submit.data:
db.session.delete(item)
db.commit()
return redirect(url_for('home.homepage'))
return render_template('admin/confirm-delete.html', item=item, form=form, title="Delete Item")
Run Code Online (Sandbox Code Playgroud)
这样,用户就不能通过在地址栏中键入特定链接来绕过删除确认屏幕,而且它还简化了代码。
正如评论中已经提到的,解决问题的一种方法是在用户发送请求时检查某个 cookie。但就我个人而言,我不会推荐这种方法,因为除非您想出某种哈希算法来哈希 cookie 值并以某种方式检查它们,否则此类 cookie 很可能会受到损害。
在我看来,最简单、最安全、最自然的方法是使用 CSRF 令牌
保护路由。/delete您可以使用Flask_WTF扩展来实现它。
总之,你必须创建类似的东西DeleteForm,然后你输入{{form.csrf_token}}你的并confirm-delete.html验证它delete_view()form.validate_on_submit()
查看他们的文档:
http://flask-wtf.readthedocs.io/en/stable/form.html
http://flask-wtf.readthedocs.io/en/stable/csrf.html
| 归档时间: |
|
| 查看次数: |
5558 次 |
| 最近记录: |