发布于2019-08-23 16:44 阅读(290) 评论(0) 点赞(2) 收藏(0)
CSRF
全拼为Cross Site Request Forgery
,译为跨站请求伪造。CSRF
指攻击者盗用了你的身份,以你的名义发送恶意请求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | from flask import Flask, render_template, make_response from flask import redirect from flask import request from flask import url_for app = Flask(__name__) @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" ) print ( '假装执行转操作,将当前登录用户的钱转账到指定账户' ) return '转账 %s 元到 %s 成功' % (money, to_account) # 渲染转换页面 response = make_response(render_template( 'temp_transfer.html' )) return response if __name__ = = '__main__' : app.run(debug = True , port = 9000 ) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <!DOCTYPE html> <html lang = "en" > <head> <meta charset = "UTF-8" > <title>登录< / title> < / head> <body> <h1>我是网站A,登录页面< / h1> <form method = "post" > <label>用户名:< / label>< input type = "text" name = "username" placeholder = "请输入用户名" ><br / > <label>密码:< / label>< input type = "password" name = "password" placeholder = "请输入密码" ><br / > < input type = "submit" value = "登录" > < / form> < / body> < / html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <!DOCTYPE html> <html lang = "en" > <head> <meta charset = "UTF-8" > <title>转账< / title> < / head> <body> <h1>我是网站A,转账页面< / h1> <form method = "post" > <label>账户:< / label>< input type = "text" name = "to_account" placeholder = "请输入要转账的账户" ><br / > <label>金额:< / label>< input type = "number" name = "money" placeholder = "请输入转账金额" ><br / > < input type = "submit" value = "转账" > < / form> < / body> < / html> |
运行测试,如果在未登录的情况下,不能直接进入转账页面,测试转账是成功的
1 2 3 4 5 6 7 8 9 10 11 | from flask import Flask from flask import render_template app = Flask(__name__) @app .route( '/' ) def index(): return render_template( 'temp_index.html' ) if __name__ = = '__main__' : app.run(debug = True , port = 8000 ) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <!DOCTYPE html> <html lang = "en" > <head> <meta charset = "UTF-8" > <title>Title< / title> < / head> <body> <h1>我是网站B< / h1> <form method = "post" action = "http://127.0.0.1:9000/transfer" > < input type = "hidden" name = "to_account" value = "999999" > < input type = "hidden" name = "money" value = "190000" hidden> < input type = "submit" value = "点击领取优惠券" > < / form> < / body> < / html> |
运行测试,在用户登录网站A的情况下,点击网站B的按钮,可以实现伪造访问
1 2 3 | # 生成 csrf_token 函数 def generate_csrf(): return bytes.decode(base64.b64encode(os.urandom( 48 ))) |
1 2 3 4 5 6 7 8 9 10 11 | @app .route( '/transfer' , methods = [ "POST" , "GET" ]) def transfer(): ... # 生成 csrf_token 的值 csrf_token = generate_csrf() # 渲染转换页面,传入 csrf_token 到模板中 response = make_response(render_template( 'temp_transfer.html' , csrf_token = csrf_token)) # 设置csrf_token到cookie中,用于提交校验 response.set_cookie( 'csrf_token' , csrf_token) return response |
1 2 3 4 5 6 | <form method = "post" > < input type = "hidden" name = "csrf_token" value = "{{ csrf_token }}" > <label>账户:< / label>< input type = "text" name = "to_account" placeholder = "请输入要转账的账户" ><br / > <label>金额:< / label>< input type = "number" name = "money" placeholder = "请输入转账金额" ><br / > < input type = "submit" value = "转账" > < / form> |
1 2 3 4 5 6 7 8 9 10 11 12 | if request.method = = "POST" : to_account = request.form.get( "to_account" ) money = request.form.get( "money" ) # 取出表单中的 csrf_token form_csrf_token = request.form.get( "csrf_token" ) # 取出 cookie 中的 csrf_token cookie_csrf_token = request.cookies.get( "csrf_token" ) # 进行对比 if cookie_csrf_token ! = form_csrf_token: return 'token校验失败,可能是非法操作' print ( '假装执行转操作,将当前登录用户的钱转账到指定账户' ) return '转账 %s 元到 %s 成功' % (money, to_account) |
运行测试,用户直接在网站 A 操作没有问题,再去网站B进行操作,发现转账不成功,因为网站 B 获取不到表单中的 csrf_token 的隐藏字段,而且浏览器有同源策略,网站B是获取不到网站A的 cookie 的,所以就解决了跨站请求伪造的问题
在 Flask 中, Flask-wtf 扩展有一套完善的 csrf 防护体系,对于我们开发者来说,使用起来非常简单
1 | app.secret_key = "#此处可以写随机字符串#" |
1 2 3 4 5 6 7 | <form method = "post" > {{ form.csrf_token() }} {{ form.username.label }} {{ form.username }}<br / > {{ form.password.label }} {{ form.password }}<br / > {{ form.password2.label }} {{ form.password2 }}<br / > {{ form.submit }} < / form> |
设置完毕,cookie 中的 csrf_token 不需要我们关心,会自动帮我们设置
1 | app.secret_key = "#此处可以写随机字符串#" |
1 2 | from flask.ext.wtf import CSRFProtect CSRFProtect(app) |
1 2 3 4 | <form method = "post" > {{ form.csrf_token }} ... < / form> |
1 2 3 | <form method = "post" action = "/" > < input type = "hidden" name = "csrf_token" value = "{{ csrf_token() }}" / > < / form> |
作者:熊猫烧香
链接:https://www.pythonheidong.com/blog/article/55393/abd5cc45c428f5aa1b9a/
来源:python黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 python黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-1
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!
python经典书籍pdf下载(56)
python shell(0)
文件(0)
运行python脚本(0)
python(2)
人工智能(0)
python基础(0)
python高级(0)
IT编程电子书大合集(1)
linux(0)
bootstrap(0)
GUI编程tkinder(0)
python基础知识点(0)
ios(0)
java-2(0)