简体   繁体   English

由于 Flask-WTF 的 CSRF 保护,Flask-Restful POST 失败

[英]Flask-Restful POST fails due CSRF protection of Flask-WTF

I am using normal flask web + flask-restful.我正在使用普通的烧瓶网+烧瓶宁静。 So I need CSRF protection for web but not for REST.所以我需要为 Web 提供 CSRF 保护,但不需要为 REST 提供保护。

The moment I enable CsrfProtect(app) of flask-wtf , all my post unit tests for flask-restful return a 400.在我启用CsrfProtect(app) flask-wtf CsrfProtect(app)的那一刻,我所有的CsrfProtect(app) flask-restful后期单元测试都返回 400。

Is there a way to disable CSRF protection for REST services since they are coming from mobile handsets without session handling anyway, hence CSRF wouldn't make much sense.有没有办法禁用 REST 服务的 CSRF 保护,因为它们来自没有会话处理的手机,因此 CSRF 没有多大意义。

This is how I test it:这是我测试它的方式:

rv = self.client.post('api/v1.0/verify-email', environ_base={'REMOTE_ADDR': '127.0.0.1'}, headers={'Content-Type':'application/json'}, data=json.dumps(data))
self.check_content_type(rv.headers)
eq_(rv.status_code, 412)

You can use the @csrf.exempt decorator , which you need to add directly on the API object, with the decorators argument ;您可以使用@csrf.exempt装饰器,您需要将其直接添加到 API 对象上,并带有decorators参数 this would apply the decorator to all API routes:这会将装饰器应用于所有API 路由:

csrf_protect = CsrfProtect(app)
api = restful.Api(app, decorators=[csrf_protect.exempt])

You cannot use resource method decorators as they are not the final view functions that the exempt decorator requires to work.您不能使用资源方法装饰器,因为它们不是exempt装饰器工作所需的最终视图函数。

It appears you cannot protect individual resources and exempt others;看来你不能保护个别资源而免除其他资源; this is a limitation in the method used by Flask-Wtf's method of recording what views are exempted.这是 Flask-Wtf 记录哪些视图被豁免的方法所使用的方法的限制。

More simple solution ( related commit ):更简单的解决方案( 相关提交):

csrf.exempt(api_blueprint)

And here is a complete demo:这是一个完整的演示:

from flask import Flask, Blueprint
from flask_wtf import CSRFProtect

app = Flask(__name__)
csrf = CSRFprotect(app)

api_blueprint = Blueprint('api', __name__)
csrf.exempt(api_blueprint)

app.register_blueprint(api_blueprint)

I had the exact same issue and I kept getting a generic 401 Unauthorized error, while my postman calls were working absolutely fine.我遇到了完全相同的问题,并且不断收到通用的 401 Unauthorized 错误,而我的邮递员呼叫工作得非常好。 It took me a while to figure out that this was because I had enabled CSRF for my web-based forms.我花了一段时间才弄清楚这是因为我为基于 Web 的表单启用了 CSRF。 But my backend calls were served by Restful endpoints and CSRF Protection doesn't work with restful calls.但是我的后端调用是由 Restful 端点提供的,CSRF 保护不适用于 Restful 调用。

Here's how I fixed it:这是我修复它的方法:

In my settings file,在我的设置文件中,

I set JWT_COOKIE_CSRF_PROTECT to False and that fixed my restful post calls.我将 JWT_COOKIE_CSRF_PROTECT 设置为 False 并修复了我宁静的帖子调用。

Note:笔记:

Since you are setting this field in the global settings file, this action will disable CSRF Protection for all the API calls.由于您是在全局设置文件中设置此字段,因此此操作将为所有 API 调用禁用 CSRF 保护。

You can also disbale CSRF protection by setting the WTF_CSRF_ENABLED to False.您还可以通过将WTF_CSRF_ENABLED设置为 False 来取消 CSRF 保护。 This comes handy in your unit tests.这在您的单元测试中很方便。 For example, when you create a test app that you use in your unit tests and disable WTF_CSRF_ENABLED the tests shouldn't throw a CSRF token missing error:例如,当您创建在单元测试中使用的测试应用程序并禁用WTF_CSRF_ENABLED ,测试不应抛出 CSRF 令牌丢失错误:

app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping({'WTF_CSRF_ENABLED':False})
app.test_client().get("/api/v1/")

A workaround to CSRF protect a single API endpoint on a flask-restful blueprint could be done by checking the path with an @app.before_request decorator and activate protection on demand.可以通过使用 @app.before_request 装饰器检查路径并按需激活保护来解决 CSRF 保护烧瓶宁静蓝图上的单个 API 端点的方法。

@app.before_request
def csrf_protect():
    if request.path.startswith("/api/v1/resource"):
        csrf.protect()

A precondition is that you have set the setting一个前提是你已经设置了设置

WTF_CSRF_CHECK_DEFAULT = False

You could set WTF_CSRF_ENABLED = False in your test_config.您可以在 test_config 中设置 WTF_CSRF_ENABLED = False。 If you only want to disable it for your tests that is.如果您只想为您的测试禁用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM