OAuthException:使用 Gunicorn 和 Flask 时没有可用的令牌

OAuthException: No token available when using Gunicorn and Flask

我一直在本地开发一个使用 Facebook 作为主要登录方法的小型网站,并且运行良好。但是,当我使用 Gunicorn 将它部署到我的 Digital Ocean Droplet 时,出现此错误:

[2015-05-05 09:15:15 +0000] [1561] [ERROR] Error handling request
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/gunicorn/workers/sync.py", line 130, in handle
    self.handle_request(listener, req, client, addr)
  File "/usr/local/lib/python2.7/dist-packages/gunicorn/workers/sync.py", line 171, in handle_request
    respiter = self.wsgi(environ, resp.start_response)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/local/lib/python2.7/dist-packages/flask_oauth.py", line 433, in decorated
    return f(*((data,) + args), **kwargs)
  File "/home/deploy/Eggsited-python/eggsited.py", line 158, in authorized
    me = facebook.get('/me')
  File "/usr/local/lib/python2.7/dist-packages/flask_oauth.py", line 211, in get
    return self.request(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flask_oauth.py", line 272, in request
    client = self.make_client(token)
  File "/usr/local/lib/python2.7/dist-packages/flask_oauth.py", line 239, in make_client
    return oauth2.Client(self._consumer, self.get_request_token(token))
  File "/usr/local/lib/python2.7/dist-packages/flask_oauth.py", line 316, in get_request_token
    raise OAuthException('No token available', type='token_missing')
OAuthException: No token available

这是我处理登录的代码:

@app.route('/login')
def login():
    if not session.get('logged_in'):
        return facebook.authorize(callback=url_for('authorized', next=request.args.get('next') or request.referrer or None, _external=True))
    return redirect(url_for('feed'))

@app.route('/login/authorized')
@facebook.authorized_handler
def authorized(resp):
    if resp is None:
        return 'Access denied: reason=%s error=%s' % (request.args['error_reason'], request.args['error_description'])
    me = facebook.get('/me')
    picture = facebook.get('/me/picture?redirect=0&height=200&width=200&type=normal&fields=url,width,height')
    session['oauth_token'] = (resp['access_token'], '')
    session['logged_in'] = True
    session['picture'] = picture.data['data']['url']
    g.db.cursor.execute('select fb_id from user where fb_id=%s', [me.data['id']])
    data = g.db.cursor.fetchone()
    if data is None:
        g.db.cursor.execute('insert into user (fb_id, first_name, last_name, picture) values (%s, %s, %s, %s)', [me.data['id'], me.data['first_name'], me.data['last_name'], picture.data['data']['url']])
        g.db.commit()
        g.db.cursor.execute('select user_id from user where fb_id=%s', [me.data['id']])
        result = g.db.cursor.fetchone()
        session['id'] = result[0]
        flash('You\'re logged in!')
        return redirect(url_for('feed'))
    g.db.cursor.execute('select user_id from user where fb_id=%s', [me.data['id']])
    result = g.db.cursor.fetchone()
    session['id'] = result[0]
    flash('You have succesfully logged in')
    return redirect(url_for('feed'))

@facebook.tokengetter
def get_facebook_oauth_token():
    return session.get('oauth_token')

我一直在谷歌搜索和谷歌搜索寻找答案,但我似乎找不到像这样的任何东西。任何指针都将不胜感激:-)

编辑: 想知道我的 nginx conf 也可能很好:

server {
    listen 80;

    server_name localhost;
    client_max_body_size 2M;

    access_log  /var/log/nginx/access.log;
    error_log  /var/log/nginx/error.log;

    location / {
        proxy_pass         http://127.0.0.1:8000/;
        proxy_redirect     default;

        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }
}

事实证明,在从 Facebook 请求数据之前请求访问令牌解决了问题。所以我的授权方法应该是这样的:

@app.route('/login/authorized')
@facebook.authorized_handler
def authorized(resp):
    if resp is None:
        return 'Access denied: reason=%s error=%s' % (request.args['error_reason'], request.args['error_description'])
    session['oauth_token'] = (resp['access_token'], '')
    me = facebook.get('/me')
    picture = facebook.get('/me/picture?redirect=0&height=200&width=200&type=normal&fields=url,width,height')
    session['logged_in'] = True
    session['picture'] = picture.data['data']['url']
    g.db.cursor.execute('select fb_id from user where fb_id=%s', [me.data['id']])
    data = g.db.cursor.fetchone()
    if data is None:
        g.db.cursor.execute('insert into user (fb_id, first_name, last_name, picture) values (%s, %s, %s, %s)', [me.data['id'], me.data['first_name'], me.data['last_name'], picture.data['data']['url']])
        g.db.commit()
        g.db.cursor.execute('select user_id from user where fb_id=%s', [me.data['id']])
        result = g.db.cursor.fetchone()
        session['id'] = result[0]
        flash('You\'re logged in!')
        return redirect(url_for('feed'))
    g.db.cursor.execute('select user_id from user where fb_id=%s', [me.data['id']])
    result = g.db.cursor.fetchone()
    session['id'] = result[0]
    flash('You have succesfully logged in')
    return redirect(url_for('feed'))

希望这可以帮助其他人:-)