编辑2:当令牌失败时,oauth给出{"error":{"message":"This authorization code has been used.","type":"OAuthException","code":100}}
编辑:在正常页面导航期间偶尔也会出现这种情况。
我第二次使用XMLHttpRequest时,我的facebook用户访问令牌即将到期。当我在应用程序中导航时,访问令牌不会过期。我正在使用Heroku的python Flask应用程序。加载页面时,会获得带有get_token
的标记:
def fbapi_get_string(path,
domain=u'graph', params=None, access_token=None,
encode_func=urllib.urlencode):
"""Make an API call"""
if not params:
params = {}
params[u'method'] = u'GET'
if access_token:
params[u'access_token'] = access_token
for k, v in params.iteritems():
if hasattr(v, 'encode'):
params[k] = v.encode('utf-8')
url = u'https://' + domain + u'.facebook.com' + path
params_encoded = encode_func(params)
url = url + params_encoded
result = requests.get(url).content
return result
def fbapi_auth(code):
params = {'client_id': app.config['FB_APP_ID'],
'redirect_uri': request.url,
'client_secret': app.config['FB_APP_SECRET'],
'code': code}
result = fbapi_get_string(path=u"/oauth/access_token?", params=params,
encode_func=simple_dict_serialisation)
print result
pairs = result.split("&", 1)
result_dict = {}
for pair in pairs:
(key, value) = pair.split("=")
result_dict[key] = value
return (result_dict["access_token"], result_dict["expires"])
def get_token():
if request.args.get('code', None):
return fbapi_auth(request.args.get('code'))[0]
cookie_key = 'fbsr_{0}'.format(FB_APP_ID)
if cookie_key in request.cookies:
c = request.cookies.get(cookie_key)
encoded_data = c.split('.', 2)
sig = encoded_data[0]
data = json.loads(urlsafe_b64decode(str(encoded_data[1]) + (64-len(encoded_data[1])%64)*"="))
if not data['algorithm'].upper() == 'HMAC-SHA256':
raise ValueError('unknown algorithm {0}'.format(data['algorithm']))
h = hmac.new(FB_APP_SECRET, digestmod=hashlib.sha256)
h.update(encoded_data[1])
expected_sig = urlsafe_b64encode(h.digest()).replace('=', '')
if sig != expected_sig:
raise ValueError('bad signature')
params = {
'client_id': FB_APP_ID,
'client_secret': FB_APP_SECRET,
'redirect_uri': '',
'code': data['code']
}
from urlparse import parse_qs
r = requests.get('https://graph.facebook.com/oauth/access_token', params=params)
token = parse_qs(r.content).get('access_token')
return token
没有令牌时,None
会返回 get_token
。如果返回None
或者用户未提供相应的权限,则会调用redirect(oauthLoginUrl())
:
def oauthLoginUrl():
fb_login_uri = ("https://www.facebook.com/dialog/oauth"
"?client_id=%s&redirect_uri=%s" %
(app.config['FB_APP_ID'], request.url))
if app.config['FBAPI_SCOPE']:
fb_login_uri += "&scope=%s" % ",".join(app.config['FBAPI_SCOPE'])
return fb_login_uri
这似乎适用于在浏览器中导航的页面,但对于XMLHttpRequests,令牌过期。当令牌过期时,这些Ajax请求的响应会产生错误代码而不是重定向。用户被告知他们的会话已过期,并被要求刷新页面。
有没有人对令牌为何与Ajax过期有任何想法?
答案 0 :(得分:0)
oauth代码不能多次使用。 heroku模板已过时。将get_token()
函数替换为:
def get_token():
if request.args.get('code', None):
token = fbapi_auth(request.args.get('code'))
session['accessToken'] = token[0]
session['expiry'] = time.time() + int(token[1])
return token[0]
# Check if we have the token already and that it has not expired
if 'accessToken' in session:
if session['expiry'] < time.time():
return None
return session['accessToken']
cookie_key = 'fbsr_{0}'.format(FB_APP_ID)
if cookie_key in request.cookies:
c = request.cookies.get(cookie_key)
encoded_data = c.split('.', 2)
sig = encoded_data[0]
data = json.loads(urlsafe_b64decode(str(encoded_data[1]) + (64-len(encoded_data[1])%64)*"="))
if not data['algorithm'].upper() == 'HMAC-SHA256':
raise ValueError('unknown algorithm {0}'.format(data['algorithm']))
h = hmac.new(FB_APP_SECRET, digestmod=hashlib.sha256)
h.update(encoded_data[1])
expected_sig = urlsafe_b64encode(h.digest()).replace('=', '')
if sig != expected_sig:
raise ValueError('bad signature')
params = {
'client_id': FB_APP_ID,
'client_secret': FB_APP_SECRET,
'redirect_uri': '',
'code': data['code']
}
from urlparse import parse_qs
r = requests.get('https://graph.facebook.com/oauth/access_token', params=params)
token = parse_qs(r.content).get('access_token')
if token:
# Save token
session['accessToken'] = token;
session['expiry'] = time.time() + int(parse_qs(r.content).get('expires'))
return token