使用request.form.get()时,是否需验证登录请求为POST?
先看两种登录路由的写法:
主流安全写法
@app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': password = request.form.get('password') if password == "pass": # 处理登录逻辑 return redirect('/index') return render_template('login.html')
对应的前端表单:
<form action='/login' method='POST'> <input type='password' id="pass" name='password'> <input type='submit' value='Login'> </form>
你的初始写法
@app.route('/login', methods=['GET', 'POST']) def login(): password = request.form.get('password') if password == "pass": # 处理登录逻辑 return redirect('/index') return render_template('login.html')
你提到两种写法都能运行,但前者更安全,你理解request.args.get('password')不验证POST的风险,但疑惑request.form.get('password')不会通过URL篡改,为什么还要验证POST?原因如下:
避免无意义的逻辑执行:当用户用GET请求访问
/login(比如直接在地址栏输入),你的代码依然会尝试从request.form取密码(结果是None),再执行判断逻辑。虽然这不会直接触发安全问题,但完全不符合HTTP语义——GET请求本来就只是用来获取登录页面,不该处理提交数据的逻辑,多余的执行步骤属于代码冗余。降低后续代码变动的风险:如果后续开发中不小心修改了代码,比如把
request.form的内容打印到日志、或者误将其返回给前端,没判断请求方法的话,GET请求下这些操作也会执行,可能导致敏感信息(哪怕是空值)意外暴露。而先判断POST的写法,能把这类操作限制在提交数据的场景里。严格遵循HTTP规范,减少攻击面:HTTP方法有明确分工,POST负责提交数据,GET负责获取资源。严格遵循规范的代码,能避免语义混淆带来的潜在问题。比如有些自动化工具会遍历站点的GET路由,如果你的登录逻辑在GET请求下也能被触发(哪怕这里不会成功),相当于给攻击者多了一个尝试入口,养成规范习惯能避免其他场景出问题。
从根源避免低级错误:虽然现在用的是
request.form,但如果后续不小心改成request.args(从URL取参数),没判断请求方法的话,密码会直接暴露在URL里,被浏览器缓存、记录到历史记录,造成严重安全隐患。提前判断请求方法,能从一开始就杜绝这种错误的发生。
内容的提问来源于stack exchange,提问作者Philip Hartfield

