这里有新鲜出炉的Python入门,程序狗速度看过来!
Python 是一种面向对象、解释型计算机程序设计语言,由Guido van Rossum于1989年底发明,第一个公开发行版发行于1991年。Python语法简洁而清晰,具有丰富和强大的类库。它常被昵称为胶水语言,它能够把用其他语言制作的各种模块(尤其是C/C++)很轻松地联结在一起。
利用QQ开放平台的API使用QQ账号登录是现在很多网站都具备的功能,而对于Flask框架来说则有Flask-OAuthlib这个现成的轮子,这里我们就来看一下Python的Flask框架应用程序实现使用QQ账号登录的方法
Flask-OAuthlib是OAuthlib的Flask扩展实现,
项目地址:
https://github.com/lepture/flask-oauthlib
主要特性:
Flask-OAuthlib提供了多个开放平台的示例代码,比如Google, Facebook, Twiter, Github, Dropbox, 豆瓣, 微博等,只是暂时没有QQ登录的示例代码。
QQ OAuth登录示例
下面是QQ登录的代码:
- import os import json from flask import Flask,
- redirect,
- url_for,
- session,
- request,
- jsonify,
- Markup from flask_oauthlib.client import OAuth
- QQ_APP_ID = os.getenv('QQ_APP_ID', '101187283') QQ_APP_KEY = os.getenv('QQ_APP_KEY', '993983549da49e384d03adfead8b2489')
- app = Flask(__name__) app.debug = True app.secret_key = 'development'oauth = OAuth(app)
- qq = oauth.remote_app('qq', consumer_key = QQ_APP_ID, consumer_secret = QQ_APP_KEY, base_url = 'https://graph.qq.com', request_token_url = None, request_token_params = {
- 'scope': 'get_user_info'
- },
- access_token_url = '/oauth2.0/token', authorize_url = '/oauth2.0/authorize', )
- def json_to_dict(x) : '''OAuthResponse class can't not parse the JSON data with content - type text / html,
- so we need reload the JSON data manually '''
- if x.find('callback ') > -1:
- pos_lb = x.find(' {
- ')
- pos_rb = x.find('
- }
- ')
- x = x[pos_lb:pos_rb + 1]
- try:
- return json.loads(x, encoding='utf - 8 ')
- except:
- return x
- def update_qq_api_request_data(data={}):
- '''Update some required parameters
- for OAuth2.0 API calls '''
- defaults = {
- 'openid ': session.get('qq_openid '),
- 'access_token ': session.get('qq_token ')[0],
- 'oauth_consumer_key ': QQ_APP_ID,
- }
- defaults.update(data)
- return defaults
- @app.route(' / ')
- def index():
- '''just
- for verify website owner here.'''
- return Markup(''' < meta property = "qc:admins"'''
- '''content = "226526754150631611006375" / >''')
- @app.route(' / user_info ')
- def get_user_info():
- if 'qq_token ' in session:
- data = update_qq_api_request_data()
- resp = qq.get(' / user / get_user_info ', data=data)
- return jsonify(status=resp.status, data=resp.data)
- return redirect(url_for('login '))
- @app.route(' / login ')
- def login():
- return qq.authorize(callback=url_for('authorized ', _external=True))
- @app.route(' / logout ')
- def logout():
- session.pop('qq_token ', None)
- return redirect(url_for('get_user_info '))
- @app.route(' / login / authorized ')
- def authorized():
- resp = qq.authorized_response()
- if resp is None:
- return 'Access denied: reason = %s error = %s ' % (
- request.args['error_reason '],
- request.args['error_description ']
- )
- session['qq_token '] = (resp['access_token '], '')
- # Get openid via access_token, openid and access_token are needed for API calls
- resp = qq.get(' / oauth2.0 / me ', {'access_token ': session['qq_token '][0]})
- resp = json_to_dict(resp.data)
- if isinstance(resp, dict):
- session['qq_openid '] = resp.get('openid ')
- return redirect(url_for('get_user_info '))
- @qq.tokengetter
- def get_qq_oauth_token():
- return session.get('qq_token ')
- if __name__ == '__main__ ':
- app.run()'
主要流程:
更多信息请参阅Flask-OAuthlib文档和QQ互联文档:
https://flask-oauthlib.readthedocs.org/
http://wiki.connect.qq.com/
关于SAE平台的特别说明
在SAE平台上,授权过程没有任何问题,当获取到access_token之后,调用API时,会在请求时(比如get, put)附加类似如下的请求头:
- headers = {u'Authorization': u'Bearer 83F40E96FB6882686F4DF1E17105D04E'}
这个请求头会引发HTTPError: HTTP Error 400: Bad request,造成请求失败。解决的办法是把键名转换成str类型,Hack代码如下:
- def convert_keys_to_string(dictionary):
- """Recursively converts dictionary keys to strings."""
- if not isinstance(dictionary, dict):
- return dictionary
- return dict((str(k), convert_keys_to_string(v))
- for k, v in dictionary.items())
- def change_qq_header(uri, headers, body):
- headers = convert_keys_to_string(headers)
- return uri, headers, body
- qq.pre_request = change_qq_header
当项目部署在SAE平台时,将这段代码放在if __name__ == '__main__'语句之前即可。
小结
OAuth2登录验证还是比较容易的,绝大多数的平台都支持标准的协议,使用通用的库可以简化开发流程。另外,QQ登录的代码已经提交到Flask-OAuthlib代码库了。
来源: http://www.phperz.com/article/17/1021/351520.html