Flask-Restful POST fails due CSRF protection of Fl

2020-05-23 20:29发布

问题:

I am using normal flask web + flask-restful. So I need CSRF protection for web but not for REST.

The moment I enable CsrfProtect(app) of flask-wtf, all my post unit tests for flask-restful return a 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.

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)

回答1:

You can use the @csrf.exempt decorator, which you need to add directly on the API object, with the decorators argument; this would apply the decorator to all API routes:

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.

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.



回答2:

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)


回答3:

I had the exact same issue and I kept getting a generic 401 Unauthorized error, while my postman calls were working absolutely fine. It took me a while to figure out that this was because I had enabled CSRF for my web-based forms. But my backend calls were served by Restful endpoints and CSRF Protection doesn't work with restful calls.

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.

Note:

Since you are setting this field in the global settings file, this action will disable CSRF Protection for all the API calls.



回答4:

You could set WTF_CSRF_ENABLED = False in your test_config. If you only want to disable it for your tests that is.