Flask:CSRF 验证失败

Posted

技术标签:

【中文标题】Flask:CSRF 验证失败【英文标题】:Flask : CSRF verification failed 【发布时间】:2015-09-11 00:22:33 【问题描述】:

我正在从 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 验证或如何禁用它?

【问题讨论】:

Flask 没有内置 CSRF 保护。你是用 Flask-WTF 还是类似的扩展来添加它? 不,我不想使用它,我不明白为什么会收到此错误。我不使用flask_wtf.csrf、CsrfProtect,也不在app.py中使用CsrfProtect(app)。 如果可能我想禁用它,但我不知道为什么 app.config['WTF_CSRF_CHECK_DEFAULT'] = False 在 app.py 中不起作用。 如果您不使用 WTF,那么 'WTF_CSRF_CHECK_DEFAULT' 将不起作用。 好的,我应该导入 Flask-WTF 或类似的扩展来使 WTF_CSRF_CHECK_DEFAULT 工作吗? 【参考方案1】:

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

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

康拉德

【讨论】:

是的,这是正确的 url,因为当我重新加载网络应用程序时它可以工作几个小时或一天,然后 CSRF 验证错误又回来了。 它回来后会一直停留到你重新加载webapp吗?还是打了几次后它会消失【参考方案2】:

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

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

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

【讨论】:

以上是关于Flask:CSRF 验证失败的主要内容,如果未能解决你的问题,请参考以下文章

Drupal 中的 CSRF 验证失败

禁止 (403) CSRF 验证失败。请求中止。即使使用 % csrf_token %

Django 1.2.4 CSRF 验证失败

某些用户的 CSRF 验证失败

Symfony:身份验证请求失败:无效的 CSRF 令牌

django CSRF 验证失败。请求中止