Flask框架——CSRF保护


CSRF攻击

CSRF全拼为Cross Site Request Forgery,译为跨站请求伪造。
CSRF指攻击者盗用了你的身份,以你的名义发送恶意请求。
包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…
造成的问题:个人隐私泄露以及财产安全。

攻击示意图:
在这里插入图片描述

如何防御CSRF攻击

csrf_token服务器内部校验过程:
表单提交
1.在表单中携带,隐藏的csrf_token,加密的 (自己设置)
2.在cookie中,设置一个sessionID (服务器设置)
在提交的时候,服务器校验过程:
(1)取出表单中的csrf_token, 使用SECRET_KEY,进行解密, 得到未加密的csrf_token
(2)通过sessionID取出,服务器内部的session空间中的,未加密的csrf_token,比较二者的值是否相等,如果相等则校验通过

非表单提交, ajax提交
1.在headers中设置csrf_token,加密的 (自己设置), 来自于cookie中的 (我们自己设置的)
2.在cookie中,设置一个sessionID (服务器设置)
在提交的时候,服务器校验过程:
(1)取出headers中的csrf_token, 使用SECRET_KEY,进行解密, 得到未加密的csrf_token
(2)通过sessionID取出,服务器内部的session空间中的,未加密的csrf_token,比较二者的值是否相等,如果相等则校验通过

Flask框架中的CSRF保护机制

csrf_token: 为了解决跨站请求伪造,⽽定义的变量
flask中提供了模块flask_wtf⾥⾯提供了⼀个类CSRFProtect来保护
使⽤流程:
1.导⼊模块: from flask_wtf import CSRFProtect
2.使⽤CSRFProtect(app), 保护应⽤程序
3.在表单中,使⽤csrf_token(), ⾃动⽣成⼀个csrf_token值,并且这个值是加密的,需要设置
SECRET_KEY
4.csrfprotect保护的时候对以下请求⽅式做校验:‘POST’, ‘PUT’, ‘PATCH’, ‘DELETE’
代码实现:
在html模板文件中表单提交里需要加上一个隐藏的字段csrf_token
在这里插入图片描述

from flask import Flask,render_template,request
from flask_wtf import CSRFProtect

app = Flask(__name__)

app.config["SECRET_KEY"] = "fjdkfkdjfdk"

CSRFProtect(app)

@app.route('/')
def index():

    return render_template("file08index.html")

@app.route('/register',methods=["POST"])
def register():

    #1.获取参数
    username = request.form.get("username")
    password = request.form.get("password")
    repassword = request.form.get("repassword")

    #2.校验,为空校验
    if not all([username,password,repassword]):
        return "参数填写不完整"

    #3.密码需要一致
    if password != repassword:
        return "密码不一致"


    return "注册成功"

if __name__ == '__main__':
    app.run(debug=True)

具体实现方法(手动添加):

@app.route('/', methods=["POST", "GET"])
def index():
    if request.method == "POST":
        # 取到表单中提交上来的参数
        username = request.form.get("username")
        password = request.form.get("password")

        if not all([username, password]):
            print('参数错误')
        else:
            print(username, password)
            if username == 'laowang' and password == '1234':
                # 状态保持,设置用户名到cookie中表示登录成功
                response = redirect(url_for('transfer'))
                response.set_cookie('username', username)
                return response
            else:
                print('密码错误')

    return render_template('temp_login.html')


#转账页面
@app.route('/transfer', methods=["POST", "GET"])
def transfer():
    # 从cookie中取到用户名
    username = request.cookies.get('username', None)
    # 如果没有取到,代表没有登录
    if not username:
        return redirect(url_for('index'))

    if request.method == "POST":
        to_account = request.form.get("to_account")
        money = request.form.get("money")


        # 取到表单中的token
        form_csrf_token = request.form.get('csrf_token')
        # cookie中的token
        cookie_csrf_token = request.cookies.get('csrf_token', "")

        # 做校验。如果校验成功,再进行转账逻辑
        if form_csrf_token != cookie_csrf_token:
            return "你是坏蛋,非法请求"



        print('假装执行转账操作,将当前登录用户的钱转账到指定账户')
        return '转账 %s 元到账号 %s 成功' % (money, to_account)



    csrf_token = generate_csrf()
    # 渲染转换页面,表单中设置csrf_token
    response = make_response(render_template('temp_transfer.html', csrf_token=csrf_token))
    # 往cookie中添加csrf_token
    response.set_cookie('csrf_token', csrf_token)



    return response


# 生成 csrf_token
def generate_csrf():
    return bytes.decode(base64.b64encode(os.urandom(48)))


if __name__ == '__main__':
    app.run(debug=True, port=9000)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值