在构建示例代码 here 时,使用 Oauthlib 通过 Facebook 进行身份验证时,我始终收到“来自 Facebook 的无效响应”错误。
我在下面概述了相关代码的各个部分。
设置:
设置 Oauth 请求对象。
未图示:导航路线和 Flask 应用初始化。
from flask_oauthlib.client import OAuth, OAuthException
oauth = OAuth()
facebook = oauth.remote_app('facebook',
base_url='https://graph.facebook.com/',
request_token_url=None,
access_token_url='/oauth/access_token',
authorize_url='https://www.facebook.com/dialog/oauth',
consumer_key=config.get("app_id"),
consumer_secret=config.get("app_secret"),
request_token_params={'scope': 'public_profile,email'}
)
@facebook.tokengetter
def get_facebook_token():
if current_user.is_authenticated():
return current_user.get_facebook_token()
else:
return None
登录处理程序:
将用户发送到此处以开始该过程,并将 facebook 回调的 url 附加到根 URL。
@app.route('/facebook/login')
def facebook_login():
return facebook.authorize(callback="http://example.com%s" % url_for('facebook_callback'))
Facebook 回调,问题根源:
从这里我可以发现返回了一个代码(大概是 token ),但 Oauthlib 无法正确解析它。
@app.route('/facebook/callback')
def facebook_callback(response):
response = facebook.authorized_response()
if response is None:
flash("You denied the request to sign in.", "error")
return redirect(url_for('index'))
if isinstance(response, OAuthException):
flash("Access denied: %s" % response.message, "error")
return redirect(url_for('index'))
# Request fails here, returns the redirect above.
通过转储请求参数,我可以相当清楚地看到,在定向到 Facebook 并成功连接后,有一个很长的 token 沿着“?code=1234567890-abcdefghijklmnop”的行返回到回调,但实际上尝试对此进行身份验证失败,并显示“来自 Facebook 的无效响应”。
这是一个示例请求转储:
ImmutableMultiDict([('code', 'AQAPedwWavTb_cBx6NVy-qy3AL5YPr780oG5tA1LfITpVwkk-kr_4I0lG6B-vlhcYEubhuKhEM46bPs-1WpWUpJzcWfhkQ64lIkdLm9uSHSqeBHBM_6zw7SDpvVmGK-JKWBpAqRJuBKenl9zslQizthox96104iiul0uYQY67cmZgPXZi9uL-mcgZ5dRj387eKJIjNninBXxwCGgFkg5kLVHYt7t0ktUH58stYlxn2f98AXuSlrIvWsA5NeHsVbM8XY0XQrDrNbCvjDmEwHQGkZ3uZRbyaecN7MAi0bM0TrZzpuQ8j3M34DnQp_v9n4ktM4')])
在使用了基于 Twitter 示例的类似代码后,我认为这可能是由于 Facebook API 更改而导致的库错误,但我将不胜感激!
最佳答案
对于将来从 Google 偶然发现此问题的任何人,我在一个可以阅读的解决方案中解决了此问题 here .
Hey there, I solved this issue in a very hacky way which I would not recommend for production environments, but I eventually found the issue a few days after my last message.
When you ask Facebook for an access token, it does NOT give you an access token in the way you might expect. What I assumed to be a failure on Facebook's side was instead a (perhaps intentional) formatting error.
What you might expect:
http://example.com/callback?access_token=00000000000
or
http://example.com/callback
with the access token passed as a POST argument in the headers.What actually happens is that Facebook responds like this:
http://example.com/callback?#access_token=0000000000
Because of this, it is -impossible- for any server side language to parse it, as the access token will now only be visible to the browser itself. It is not passed to the backend whatsoever.
捕获请求:
@app.route('/facebook/translate', methods=['GET'])
def facebook_translate():
# Facebook responds with the access token as ?#access_token,
# rather than ?access_token, which is only accessible to the browser.
# This part is where things get really, really dumb.
return ''' <script type="text/javascript">
var token = window.location.href.split("access_token=")[1];
window.location = "/facebook/callback?access_token=" + token;
</script> '''
照常进行:
@app.route('/facebook/callback', methods=['GET', 'POST'])
def facebook_callback():
access_token = request.args.get("access_token")
if access_token == "undefined":
flash("You denied the request to sign in.", "error")
return redirect(url_for('index'))
graph = facebooksdk.GraphAPI(access_token)
profile = graph.get_object("me")
关于python - 使用 Flask-Oauthlib 向 Facebook 进行身份验证时出现 "Invalid Response from Facebook",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26726926/