Flask:CSRF验证失败

时间:2015-06-24 16:58:37

标签: python ios flask csrf csrf-protection

我正在从iOS客户端发送POST请求

-(void)loadFavorite:(NSArray*)favorites{

    //data and url preparation

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
    [request setHTTPMethod:@"POST"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setValue:@"https://example.com" forHTTPHeaderField: @"Referer"];

    [request setValue:[NSString stringWithFormat:@"%tu", [requestData length]] forHTTPHeaderField:@"Content-Length"];
    [request setHTTPBody: requestData];

    if ([Tools isNetWorkConnectionAvailable]) {
        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
            //response handle
    }
}

以下是回复:

<div id="summary">
  <h1>Forbidden <span>(403)</span></h1>
  <p>CSRF verification failed. Request aborted.</p>
</div>

我使用Flask框架和pythonanywhere进行托管。

当我重新加载python脚本时它工作正常但几小时/几天后CSRF验证失败错误重新出现。

即使我尝试在app.py中使用以下命令禁用CSRF验证:

app.config['WTF_CSRF_CHECK_DEFAULT'] = False

App.py脚本:

//some import error handlers ...

app = Flask(__name__)
app.config['WTF_CSRF_CHECK_DEFAULT'] = False

@app.route('/api/favorites', methods=['POST'])
def get_favorites_beaches():
    if not request.json or not 'favorite' in request.json:
        abort(400)
    //data process

if __name__ == '__main__':
    app.run(host='0.0.0.0',debug=True)

如何正确实施CSRF验证或如何禁用它?

2 个答案:

答案 0 :(得分:1)

PythonAnywhere开发人员在这里,重新发布我们刚刚在论坛上发布的内容。这在我们的托管平台上是一个相当模糊的问题,我们刚刚推出了修复它的系统补丁。

以下是它的原因:如果Web应用由于某种原因(系统重启,某些类型的故障,过多的资源使用,可能是休眠)而关闭,那么只有GET请求才会将其唤醒。特别是POST请求会被CSRF错误拒绝(由我们的代码生成,这意味着启动Web应用程序),并且应用程序不会被唤醒。因此,如果您的应用程序是主要处理POST请求的应用程序,您会看到此问题。这肯定似乎符合你所描述的问题。

我们的新代码会在收到POST时唤醒应用程序。一个小问题仍然存在 - 第一个唤醒它的POST请求将收到“503 Service Unavailable”响应,并且“retry-after”标头设置为“5”。如果你处理这个并重试,那么下一个请求将起作用。我们相信浏览器会自动执行此操作,但遗憾的是,请求库不会默认执行。

答案 1 :(得分:0)

您的代码中有一行[request setValue:@"https://example.com" forHTTPHeaderField: @"Referer"];

你没有把它设置为正确的网址吗?错误的引用是您获得跨站点错误的一种方式。

康拉德