一、什么是CSRFToken?
- CSRF全拼为Cross Site Request Forgery,译为跨站请求伪造。
- CSRF指攻击者盗用了你的身份,以你的名义发送恶意请求。
包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账… - 造成的问题:个人隐私泄露以及财产安全。
二、 CSRF攻击示意图
客户端访问服务器时没有同服务器做安全验证
三 、防止CSRF攻击
- 在客户端向后端请求界面数据的时候,后端会往响应中的 cookie 中设置 csrf_token 的值
- 在 Form 表单中添加一个隐藏的的字段,值也是 csrf_token在用户点击提交的时候,会带上这两个值向后台发起请求
- 后端接受到请求,以会以下几件事件:
1.从 cookie中取出 csrf_token
2.从 表单数据中取出来隐藏的 csrf_token 的值
3.进行对比 - 如果比较之后两值一样,那么代表是正常的请求,如果没取到或者比较不一样,代表不是正常的请求,不执行下一步操作
提示:代码展示:见<< webA >>, << webB >>文件
3.1 手动解决
- 在cookie增加一个csrf_token
- 在表单中增加一个csrf_token
- 校验: 取出cookie和表单中的csrf_token比较如果二者一致那么是正常请求
- 具体过程,看keynote图解
3.2 CSRFProtect解决csrf
- 使用流程:
- 1.安装扩展包
pip install flask-wtf
- 2.导入包
from flask_wtf.csrf import CSRFProtect
- 3.创建CSRFProtect对象,保护app对象
- 4.设置SECRET_KEY,便于csrf_token加密
- 5.需要在表单中设置csrf_token隐藏字段即可
- 1.安装扩展包
CSRFProtect一旦保护了app之后, 会对’POST’, ‘PUT’, ‘PATCH’, 'DELETE’做校验.
四、代码示例
4.1 后端代码
from flask import Flask, render_template, request
from flask_wtf.csrf import CSRFProtect
app = Flask(__name__)
# 设置密码
app.config["SECRET_KEY"] = "tianwanggaidihu"
# 保护app
CSRFProtect(app)
@app.route('/', methods=["GET", "POST"])
def hello_world():
# 1.如果是GET请求,直接返回注册页面
if request.method == "GET":
return render_template("file16register.html")
else:
# 2.如果是POST请求,处理注册业务
# 2.1获取参数
username = request.form.get("username")
password = request.form.get("password")
repassword = request.form.get("repassword")
# 2.2校验参数,为空校验
if not all([username, password, repassword]):
return "参数填写不全"
# 2.3两次密码是否一致
if password != repassword:
return "两次密码输入不一致"
# 2.4返回注册成功
return "恭喜你, 注册成功"
if __name__ == '__main__':
app.run(debug=True)
4.2 前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
{# 只要使用了CSRFProtect保护app,那么可以直接使用csrf_token()方法获取csrf_token值 #}
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
确认密码:<input type="password" name="repassword"><br>
<input type="submit" value="注册">
</form>
</body>
</html>