在flask中开启csrf保护
让所有的视图受到CSRF保护,需要扩展 CsrfProtect模块
1 2
| from flask_wtf.csrf import CsrfProtect CsrfProtect(app)
|
csrf也支持惰性加载
1 2 3 4 5 6
| from flask_wtf.csrf import CsrfProtect csrf = CsrfProtect()
def create_app(): app = Flask(__name__) csrf.init_app(app)
|
配置
- app.config[“SECRET_KEY”]:csrf保护需要app设置盐
- app.config[“WTF_CSRF_CHECK_DEFAULT”] 为 False:在所有的视图中禁用CSRF保护
视图单独配置
当全局开启 csrf 时,可选择部分视图关闭
FBV 关闭 (基于函数的视图)
如果你想要某些路由不进行csrf验证,使用csrf.exempt
放弃验证
1 2 3 4
| @csrf.exempt @app.route('/foo', methods=('GET', 'POST')) def my_handler(): return 'ok'
|
CBV 关闭 (基于类的视图)
1 2 3 4 5 6 7
| class IndexView(views.View): methods = ['GET'] # 允许的method decorators = [csrf.exempt] # 装饰器,把放弃验证的装饰器写到这里 def dispatch_request(self): print('Index') return 'Index!' app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))
|
当全局关闭 csrf 时,可选择部分视图开启
FBV 关闭 (基于函数的视图)
默认情况下也可以在所有的视图中禁用 CSRF 保护,通过设置 WTF_CSRF_CHECK_DEFAULT 为 False,仅仅当需要的时候选择调用 csrf.protect()。这也能够在检查 CSRF 令牌前做一些预先处理
1 2 3 4 5 6 7
| @app.before_request def check_csrf(): if not is_oauth(request): csrf.protect() ```
#### CBV 关闭 (基于类的视图)
|
class IndexView(views.View):
methods = [‘GET’] # 允许的method
decorators = [csrf.protect] # 装饰器,把放弃验证的装饰器写到这里
def dispatch_request(self):
print(‘Index’)
return ‘Index!’
app.add_url_rule(‘/index’, view_func=IndexView.as_view(name=’index’))
1 2 3 4
| ## 页面添加csrf
在表单中添加csrf验证
|
方式一:
方式二:(推荐)
注:因为hexo 的某些原因,value 的值应该是 csrf_token(), 为了防止冲突,下面写的是 csrf_token,
1 2 3 4
| 不用表单,通过ajax发送post请求成为可能,flask 0.9后的版本可用。如果你使用了 CsrfProtect(app),你可以通过 {{ csrf_token() }} 获取 CSRF 令牌。这个方法在每个模板中都可以使用,你并不需要担心在没有表单时如何渲染 CSRF 令牌字段。
官方推荐在<meta>标签中渲染CSRF令牌:
|
# 注:因为hexo 的某些原因,content 的值应该是 csrf_token(), 为了防止冲突,下面写的是 csrf_token,
# 注:因为hexo 的某些原因,csrftoken 的值应该是 csrf_token(), 为了防止冲突,下面写的是 csrf_token,
1 2 3 4 5
|
## csrf不通过会返回400响应
你可以自定义返回的页面
|
@csrf.error_handler
def csrf_error(reason):
return render_template('csrf_error.html', reason=reason), 400
1 2 3 4 5 6 7
|
## 提交带csrf的请求请求
无论什么时候发送 Ajax POST 请求,都要添加X-CSRFToken请求头
### AJAX 方法一:
|
# 首先在html文件里面的head标签里面添加meta标签
# 注:因为hexo 的某些原因,content 的值应该是 csrf_token(), 为了防止冲突,下面写的是 csrf_token,
然后在script里面使用jquery获取