flask 项目之中实现跨域请求保护
1,对一个应用app开启一个保护,跨域请求针对的是所有的请求,包括get
from flask_wtf.csrf import CSRFProtect, generate_csrf CSRFProtect(app)
2,浏览器发送请求,服务器给每次请求设置 csrf_token值
# 请求钩子,每次请求都会设置 csrf_token值,视图函数执行之后调用! # 在每次请求之后, 生成csrf_token, 设置到cookie中,对响应进行最后的处理! @app.after_request def after_request(response): # token生成后,会缓存起来, 多次生成仍是同一个 csrf_token = generate_csrf() # WTF扩展会自动将corf_token存入session response.set_cookie('csrf_token', csrf_token) return response
3,前端将cookie之中的csrf_token之中的设置到自己的请求之中
如果ajax 来实现数据交互
$.ajax({ url: "/user/base_info", type: "post", contentType: "application/json", headers: { "X-CSRFToken": getCookie("csrf_token") }, data: JSON.stringify(params), success: function (resp) { if (resp.errno == "0") { // 更新父窗口内容 $('.user_center_name', parent.document).html(params['nick_name']) $('#nick_name', parent.document).html(params['nick_name']) $('.input_sub').blur() } else { alert(resp.errmsg) } } })
如果是表单,可以是表单内任意一个标签设置csrf_token()
<form method="post" class="login_form"> <h1 class="login_title">用户登录</h1> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"> <input type="text" name="username" placeholder="用户名" class="input_txt"> <input type="password" name="password" placeholder="密码" class="input_txt"> {% if errmsg %} <div class="error_tip" style="display: block">{{ errmsg }}</div> {% endif %} <input type="submit" value="登 录" class="input_sub"> </form>
4,后端收到请求之后会将csrf_token() 值进行比对,如果相同就可以认为不是钓鱼网站的请求!
以下是'模拟'CSRFProtect 类的操作,在执行表单提交会进行以下操作。
''' 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) '''