Nitro's

Mar 11, 2013 - Comments - dev tech

基于GAE的新浪微博 QQ空间 豆瓣 OAuth2.0 认证(待续)

-- coding: utf-8 --

from xml.dom.minidom import parseString
from google.appengine.api import urlfetch
from google.appengine.ext import db
from xml.parsers.expat import ExpatError

from oauth2 import *

import os
import jinja2
import urllib
import urlparse
import json
import webapp2

site = {'douban':{'appID':   '',
                  'appKey':  '',
                  'code_url':'https://www.douban.com/service/auth2/auth',
                  'acc_url': 'https://www.douban.com/service/auth2/token',
                  'acc_method':'POST',
                  'me_url':  'https://api.douban.com/people/%40me'},
        'weibo': {'appID':'',
                  'appKey':'',
                  'code_url':'https://api.weibo.com/oauth2/authorize',
                  'acc_url':'https://api.weibo.com/oauth2/access_token',
                  'acc_method':'POST',
                  'me_url':'https://api.weibo.com/2/users/show.json'},
        'qq':    {'appID':'',
                  'appKey':'',
                  'code_url':'https://graph.qq.com/oauth2.0/authorize',
                  'acc_url':'https://graph.qq.com/oauth2.0/token',
                  'acc_method':'GET',
                  'me_url':'https://graph.qq.com/user/get_user_info'}}

HOST_ADDR = "http://www.example.com"
rootpath = os.path.dirname(__file__)
jinja_environment = jinja2.Environment(loader = jinja2.FileSystemLoader(rootpath))

class get_authorization(webapp2.RequestHandler):
    def get(self,typ):
        if typ in site.keys():
            redirect_uri = HOST_ADDR+'/getinfo/'+typ
            url = OAuth2().get_authorization(site[typ]['appID'],site[typ]['code_url'],redirect_uri)
            self.redirect(url)
class get_access(webapp2.RequestHandler):
    def get(self,typ):

        access_token = ''
        uid = 0

        if typ in site.keys():
            code = self.request.get('code')
            data = OAuth2().get_access(site[typ]['appID'], site[typ]['appKey'],
                                       site[typ]['acc_method'],code,
                                       site[typ]['acc_url'],HOST_ADDR+'/getinfo/'+typ)
            if typ == 'douban':
                """redirect_uri?error=denied"""
                error = self.request.get('error')
                if code == '' and error :
                    self.response.write(error)
                    return                
                """{"access_token":"","douban_user_id":"","expires_in":}"""
                json_obj = json.loads(data)                    
                if json_obj.has_key('access_token'):
                    access_token = json_obj['access_token']
                    uid = json_obj['douban_user_id']
                else:
                    """{"code":,"msg":"","request":""}"""
                    self.response.write(json_obj['msg'])
                    return
            if typ == 'qq':
                """code=&msg="""
                msg = self.request.get('msg')
                if code == '' and msg :
                    self.response.write(msg)
                    return                
                """access_token=&expires_in="""
                params = urlparse.parse_qs(data,True)
                if 'access_token' in params.keys():
                    access_token = params['access_token'][0]
                    #QQ return the access_token ,expire_in but it didn't contain openid
                    #the openid need request it separately
                    try:
                        req_url = 'https://graph.qq.com/oauth2.0/me?access_token='+access_token
                        """callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} );"""
                        content = urlfetch.fetch(req_url).content
                        json_obj = content.split(' ')[1]
                        uid = json.loads(json_obj)['openid']                        
                    except urlfetch.Error:
                        self.response.write('urlfetch.Error')
                        return 
                    except ValueError:
                        self.response.write('ValueError')
                        return 
            if typ == 'weibo':
                """redirect_uri?error_uri=&error=&error_description=&error_code="""
                error_description = self.request.get('error_description')
                if error_description and code == '':
                    self.response.write(error_description)
                    return

                """{"access_token": "", "expires_in":,"remind_in":"","uid":""}"""
                json_obj = json.loads(data)
                if json_obj.has_key('access_token'):
                    access_token = json_obj['access_token']
                    uid = json_obj['uid']
                else:
                    """{"error":"","error_code":,"error_description":""}"""
                    self.response.write(json_obj['error_description'])
                    return
            if (not check_exist_user(typ,access_token,uid)):
                #access_token save to Token Table and return the record ID
                Token(xid=uid,
                      xaccToken=access_token,
                      xorigin=typ).put()
                self.response.write("Come on~")
                return
        else:
            self.response.write('URL error')
            return

def check_exist_user(typ,access_token,uid):
    #exit the user and update the access_token
    tokens = db.GqlQuery("SELECT * FROM Token WHERE xid=:1 and xorigin=:2",uid,typ)
    token = tokens.get()
    if token != None:
        token.xaccToken = access_token
        token.put()
        return True
    return False
class Token(db.Model):
    xid = db.StringProperty(default='')
    xorigin = db.StringProperty(default='site')
    xaccToken = db.StringProperty(default='')
class MainHandler(webapp2.RequestHandler):
    def get(self):
        template = jinja_environment.get_template('view/index.html')
        self.response.write(template.render({}))

app = webapp2.WSGIApplication([('/', MainHandler),
                               ('/login/(.*)',get_authorization),
                               ('/getinfo/(.*)',get_access)],
                              debug=True)

附:OAuth2.0通用函数