问题陈述
我正在使用Flask网络应用程序,该应用程序显示表格中的项目列表。用户可以选择一行并点击Delete
按钮删除该项目。但是,在从数据库中删除项目之前,用户首先被路由到确认屏幕,其中显示一些项目详细信息以及Confirm
按钮。确认页面的网址遵循以下模式:dashboard/confirm-delete/<id>
,实际删除页面的网址遵循以下模式:dashboard/delete/<id>
。有关详细信息,请参阅下面的admin/views.py
。
虽然系统正常运行,但我遇到的问题是,用户只需在地址栏中输入dashboard/delete/<id>
,其中<id>
被实际的商品ID替换,就可以跳过确认页面。< / p>
问题
有没有办法阻止用户访问dashboard/delete/<id>
,除非他们先去dashboard/confirm-delete/<id>
(确认屏幕)?或者,我的方法是错误的,是否有更好的方法?
当前代码:
在选择行并且按下删除按钮时调用的dashboard.html
页面中的函数:
$('#remove').click(function () {
var id = getId();
window.location.href="/dashboard/confirm-delete" + $.trim(id);
});
confirm-delete.html
中的确认按钮(删除确认页面):
<a class="btn btn-default" href="{{ url_for('admin.delete_item', id=item.id) }}" role="button">Confirm Delete</a>
我的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'))
解
根据标记为已接受的答案,我解决了以下问题:
首先,我创建了一个新表单来处理Submit
页面中的confirm-delete.html
按钮:
admin/forms.py
:
from flask_wtf import FlaskForm
from wtforms import SubmitField
class DeleteForm(FlaskForm):
submit = SubmitField('Confirm')
我将Confirm Button
代码替换为confirm-delete.html
:
<form method="post">
{{ form.csrf_token }}
{{ form.submit }}
</form>
最后,我合并了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")
这样,用户无法通过在地址栏中键入特定链接来绕过删除确认屏幕,而且还可以简化代码。
答案 0 :(得分:2)
正如评论中已经提到的,解决问题的一种方法是在用户发送请求时检查某个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
答案 1 :(得分:0)
我会将删除页面设为POST。浏览器可能会跳过GET请求或尝试多次,您无法控制它。抓取工具可以关注匿名删除链接并删除您的所有Wiki文章。浏览器预取程序可以预取注销链接。
REST纯粹主义者会坚持使用GET,POST,DELETE和PUT方法来实现其预期目的。
所以,
在HTML中
<form action='/dashboard/delete/{{id}}' method='post'>
在Flask中
@app.route('/dashboard/delete/<int:id>', methods=['POST'])
def delete(id):
答案 2 :(得分:0)
我认为括号有误。 @groups_required(['admin'})
应该吗? @groups_required(['admin'])