diff --git a/README.md b/README.md index 2a4ea84..babd74a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ - 支持文章全文搜索。 - 完整的评论功能,包括发表回复评论,以及评论的邮件提醒,支持`Markdown`。 - 侧边栏功能,最新文章,最多阅读,标签云等。 -- 支持Oauth登陆,现已有Google,GitHub,facebook,微博登录。 +- 支持Oauth登陆,现已有Google,GitHub,facebook,微博,QQ登录。 - 支持`Memcache`缓存,支持缓存自动刷新。 - 简单的SEO功能,新建文章等会自动通知Google和百度。 - 集成了简单的图床功能。 diff --git a/oauth/models.py b/oauth/models.py index 9527d78..63b3c06 100644 --- a/oauth/models.py +++ b/oauth/models.py @@ -35,6 +35,7 @@ class OAuthConfig(models.Model): ('google', '谷歌'), ('github', 'GitHub'), ('facebook', 'FaceBook'), + ('qq', 'QQ'), ) type = models.CharField('类型', max_length=10, choices=TYPE, default='a') appkey = models.CharField(max_length=200, verbose_name='AppKey') diff --git a/oauth/oauthmanager.py b/oauth/oauthmanager.py index 22b2784..b3a4791 100644 --- a/oauth/oauthmanager.py +++ b/oauth/oauthmanager.py @@ -61,10 +61,12 @@ class BaseOauthManager(metaclass=ABCMeta): def do_get(self, url, params): rsp = requests.get(url=url, params=params) + logger.info(rsp.text) return rsp.text def do_post(self, url, params): rsp = requests.post(url, params) + logger.info(rsp.text) return rsp.text def get_config(self): @@ -272,7 +274,7 @@ class GitHubOauthManager(BaseOauthManager): user.type = 'github' user.token = self.access_token user.matedata = rsp - if datas['email']: + if 'email' in datas and datas['email']: user.email = datas['email'] return user @@ -339,9 +341,9 @@ class FaceBookOauthManager(BaseOauthManager): user.type = 'facebook' user.token = self.access_token user.matedata = rsp - if datas['email']: + if 'email' in datas and datas['email']: user.email = datas['email'] - if datas['picture'] and datas['picture']['data'] and datas['picture']['data']['url']: + if 'picture' in datas and datas['picture'] and datas['picture']['data'] and datas['picture']['data']['url']: user.picture = str(datas['picture']['data']['url']) return user except Exception as e: @@ -349,6 +351,81 @@ class FaceBookOauthManager(BaseOauthManager): return None +class QQOauthManager(BaseOauthManager): + AUTH_URL = 'https://graph.qq.com/oauth2.0/authorize' + TOKEN_URL = 'https://graph.qq.com/oauth2.0/token' + API_URL = 'https://graph.qq.com/user/get_user_info' + OPEN_ID_URL = 'https://graph.qq.com/oauth2.0/me' + ICON_NAME = 'qq' + + def __init__(self, access_token=None, openid=None): + config = self.get_config() + self.client_id = config.appkey if config else '' + self.client_secret = config.appsecret if config else '' + self.callback_url = config.callback_url if config else '' + super(QQOauthManager, self).__init__(access_token=access_token, openid=openid) + + def get_authorization_url(self, nexturl='/'): + params = { + 'response_type': 'code', + 'client_id': self.client_id, + 'redirect_uri': self.callback_url + '&next_url=' + nexturl, + } + url = self.AUTH_URL + "?" + urllib.parse.urlencode(params) + return url + + def get_access_token_by_code(self, code): + params = { + 'grant_type': 'authorization_code', + 'client_id': self.client_id, + 'client_secret': self.client_secret, + 'code': code, + 'redirect_uri': self.callback_url + } + rsp = self.do_get(self.TOKEN_URL, params) + if rsp: + d = urllib.parse.parse_qs(rsp) + token = d['access_token'] + self.access_token = token + return token + + def get_open_id(self): + if self.is_access_token_set: + params = { + 'access_token': self.access_token + } + rsp = self.do_get(self.OPEN_ID_URL, params) + if rsp: + rsp = rsp.replace('callback(', '').replace(')', '').replace(';', '') + obj = json.loads(rsp) + openid = str(obj['openid']) + self.openid = openid + return openid + + def get_oauth_userinfo(self): + openid = self.get_open_id() + if openid: + params = { + 'access_token': self.access_token, + 'oauth_consumer_key': self.client_id, + 'openid': self.openid + } + rsp = self.do_get(self.API_URL, params) + logger.info(rsp) + obj = json.loads(rsp) + user = OAuthUser() + user.nikename = obj['nickname'] + user.openid = openid + user.type = 'qq' + user.token = self.access_token + user.matedata = rsp + if 'email' in obj: + user.email = obj['email'] + if 'figureurl' in obj: + user.picture = str(obj['figureurl']) + return user + + def get_oauth_apps(): configs = OAuthConfig.objects.filter(is_enable=True).all() if not configs: diff --git a/requirements.txt b/requirements.txt index d2c6e73..72b4e3b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ appdirs==1.4.3 asn1crypto==0.24.0 astroid==2.0.4 bottle==0.12.13 -certifi==2018.8.24 +certifi==2018.10.15 cffi==1.11.5 chardet==3.0.4 coverage==4.5.1 @@ -23,11 +23,11 @@ jsonpickle==1.0 lazy-object-proxy==1.3.1 markdown2==2.3.6 mccabe==0.6.1 -mistune==0.8.3 +mistune==0.8.4 olefile==0.46 packaging==18.0 Pillow==5.3.0 -pycparser==2.18 +pycparser==2.19 Pygments==2.2.0 pylint==2.1.1 PyMySQL==0.9.2 @@ -37,12 +37,12 @@ python-slugify==1.2.6 pytz==2018.5 raven==6.9.0 rcssmin==1.0.6 -requests==2.19.1 +requests==2.20.0 rjsmin==1.0.12 six==1.11.0 sqlparse==0.2.4 Unidecode==1.0.22 -urllib3==1.23 +urllib3==1.24 webencodings==0.5.1 WeRoBot==1.6.0 Whoosh==2.7.4 diff --git a/templates/oauth/bindsuccess.html b/templates/oauth/bindsuccess.html index e664a75..4bee77c 100644 --- a/templates/oauth/bindsuccess.html +++ b/templates/oauth/bindsuccess.html @@ -13,9 +13,9 @@
- Sign In + 登录 | - Home Page + 回到首页
diff --git a/templates/oauth/require_email.html b/templates/oauth/require_email.html index a8ebb95..3adef12 100644 --- a/templates/oauth/require_email.html +++ b/templates/oauth/require_email.html @@ -4,7 +4,7 @@ {% block content %}
-

Binding E-mail account

+

绑定您的邮箱账号

{% if picture %} @@ -25,7 +25,7 @@ {% endfor %} - + {% comment %}
@@ -39,7 +39,7 @@

- Sign In + 登录

diff --git a/travis_test/requirements.txt b/travis_test/requirements.txt index d2c6e73..2aceac8 100644 --- a/travis_test/requirements.txt +++ b/travis_test/requirements.txt @@ -2,7 +2,7 @@ appdirs==1.4.3 asn1crypto==0.24.0 astroid==2.0.4 bottle==0.12.13 -certifi==2018.8.24 +certifi==2018.10.15 cffi==1.11.5 chardet==3.0.4 coverage==4.5.1 @@ -23,26 +23,25 @@ jsonpickle==1.0 lazy-object-proxy==1.3.1 markdown2==2.3.6 mccabe==0.6.1 -mistune==0.8.3 +mistune==0.8.4 olefile==0.46 packaging==18.0 Pillow==5.3.0 -pycparser==2.18 +pycparser==2.19 Pygments==2.2.0 pylint==2.1.1 PyMySQL==0.9.2 pyparsing==2.2.2 -python-memcached==1.59 python-slugify==1.2.6 pytz==2018.5 raven==6.9.0 rcssmin==1.0.6 -requests==2.19.1 +requests==2.20.0 rjsmin==1.0.12 six==1.11.0 sqlparse==0.2.4 Unidecode==1.0.22 -urllib3==1.23 +urllib3==1.24 webencodings==0.5.1 WeRoBot==1.6.0 Whoosh==2.7.4