比較和測試了一下找到的社交登入模組. 覺得 social-oauth 是比較可控和靈巧. 不過他本身是一個專注於中國內地社交的模組. 所以就沒自帶 Facebook, Twitter 的支持. 那只好自幹一個 Provider 來測試.筆記一下.
結構大約是
social/providers/facebook.py
social/routes/index.py
當中 index.py 大約是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 from socialoauth import socialsitesfrom socialoauth.utils import import_oauth_classfrom socialoauth.exception import SocialAPIErrorapp_name = __name__.split('.' )[0 ] socialsites.config({ 'facebook' : ('{0}.providers.facebook.Facebook' .format(app_name), 1 , 'Facebook' , { 'redirect_uri' : 'http://sub.domain.com/login/oauth/facebook' , 'client_id' : 'SOME ID' , 'client_secret' : 'SOME KEY' , 'scope' : ['email' ] }) }) @app.route('/') def index () : user = session.get('user' ) return render_template('index.html' , user=user) @app.route('/login') def login () : connections = dict() for socialsite in socialsites.list_sites(): provider = import_oauth_class(socialsite)() connections[provider.site_name] = provider return render_template('login.html' , connections=connections) @app.route('/login/oauth/<provider>') def login_oauth (provider) : code = request.args.get('code' ) if not code: redirect(url_for('index.index' )) socialsite = import_oauth_class(socialsites[provider])() try : socialsite.get_access_token(code) except SocialAPIError as e: print e.site_name print e.url print e.error_msg raise session['user' ] = socialsite return redirect(url_for('index.index' ))
而 facebook.py 就是這樣 當中 parse_token_response 的內容可以再按需求增加 裡面的資料目前設定成和其他內置的 providers/sites 是一樣的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 from socialoauth.sites.base import OAuth2class Facebook (OAuth2) : GRAPH_URL = 'https://graph.facebook.com' AUTHORIZE_URL = 'https://www.facebook.com/dialog/oauth' ACCESS_TOKEN_URL = '{0}/oauth/access_token' .format(GRAPH_URL) SMALL_IMAGE = '{0}/{1}/picture' LARGE_IMAGE = '{0}/{1}/picture?type=large' def build_api_url (self, url) : return url def build_api_data (self, **kwargs) : data = { 'access_token' : self.access_token } data.update(kwargs) return data def parse_token_response (self, res) : res = res.split('&' ) res = [_r.split('=' ) for _r in res] res = dict(res) self.access_token = res['access_token' ] self.expires_in = int(res['expires' ]) self.refresh_token = None res = self.http_get('https://graph.facebook.com/me' , { 'access_token' : self.access_token }) self.uid = res['id' ] self.name = res['username' ] self.avatar = self.SMALL_IMAGE.format(self.GRAPH_URL, res['username' ]) self.avatar_large = self.LARGE_IMAGE.format(self.GRAPH_URL, res['username' ]) def get_access_token (self, code) : super(Facebook, self).get_access_token(code, method='GET' , parse=False )