QQ登录:即我们所说的第三方登录,是指用户可以不在本项目中输入密码,而直接通过第三方的验证,成功登录本项目。
- QQ互联开发者申请步骤
若想实现QQ登录,需要成为QQ互联的开发者,审核通过才可实现。 - 相关连接:http://wiki.connect.qq.com/%E6%88%90%E4%B8%BA%E5%BC%80%E5%8F%91%E8%80%85
- QQ互联应用申请步骤
- 成为QQ互联开发者后,还需创建应用,即获取本项目对应与QQ互联的应用ID。
相关连接:http://wiki.connect.qq.com/__trashed-2 - 网站对接QQ登录步骤
- QQ互联提供有开发文档,帮助开发者实现QQ登录。
相关连接:http://wiki.connect.qq.com/%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C_oauth2-0 - QQ登录流程分析
定义QQ登录模型类
QQ登录成功后,我们需要将QQ用户和商场用户关联到一起,方便下次QQ登录时使用,所以我们选择使用MySQL数据库进行存储。
定义模型类基类
为了给项目中模型类补充数据创建时间和更新时间两个字段,我们需要定义模型类基类。 在lgshop.utils/models.py文件中创建模型类基类。
from django.db import models
class BaseModel(models.Model):
"""为模型类补充字段"""
create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
class Meta:
abstract = True # 说明是抽象模型类, 用于继承使用,数据库迁移时不会创建BaseModel的表
定义QQ登录模型类
创建一个新的应用oauth,用来实现QQ第三方认证登录。
# oauth
path(r'oauth/', include('oauth.urls')),
在oauth/models.py中定义QQ身份(openid)与用户模型类User的关联关系
from django.db import models
from meiduo_mall.utils.models import BaseModel
# Create your models here.s
class OAuthQQUser(BaseModel):
"""QQ登录用户数据"""
user = models.ForeignKey('users.User', on_delete=models.CASCADE, verbose_name='用户')
openid = models.C harField(max_length=64, verbose_name='openid', db_index=True)
class Meta:
db_table = 'tb_oauth_qq'
verbose_name = 'QQ登录用户数据'
verbose_name_plural = verbose_name
迁移QQ登录模型类
python manage.py makemigrations
python manage.py migrate
QQLoginTool介绍
该工具封装了QQ登录时对接QQ互联接口的请求操作。可用于快速实现QQ登录。
QQLoginTool安装
pip install QQLoginTool
QQLoginTool使用说明
- 导入
from QQLoginTool.QQtool import OAuthQQ
- 初始化OAuthQQ对象
oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI, state=next)
- 获取QQ登录扫码页面,扫码后得到Authorization Code
login_url = oauth.get_qq_url()
- 通过Authorization Code获取Access Token
access_token = oauth.get_access_token(code)
- 通过Access Token获取OpenID
openid = oauth.get_open_id(access_token)
获取openid
待处理业务逻辑
提取code请求参数
使用code向QQ服务器请求access_token
使用access_token向QQ服务器请求openid
使用openid查询该QQ用户是否在商城中绑定过用户
如果openid已绑定商城用户,直接生成JWT token,并返回
如果openid没绑定商城用户,创建用户并绑定到openid
- 后端逻辑实现
class QQAuthURLView(View):
"""提供QQ登录页面网址
https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=xxx&redirect_uri=xxx&state=xxx
"""
def get(self, request):
# next表示从哪个页面进入到的登录页面,将来登录成功后,就自动回到那个页面
next = request.GET.get('next')
# 获取QQ登录页面网址
oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI, state=next)
login_url = oauth.get_qq_url()
return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'login_url':login_url})
使用access_token向QQ服务器请求openid
class QQAuthUserView(View):
"""用户扫码登录的回调处理"""
def get(self, request):
"""Oauth2.0认证"""
# 提取code请求参数
code = request.GET.get('code')
if not code:
return http.HttpResponseForbidden('缺少code')
# 创建工具对象
oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI)
try:
# 使用code向QQ服务器请求access_token
access_token = oauth.get_access_token(code)
# 使用access_token向QQ服务器请求openid
openid = oauth.get_open_id(access_token)
except Exception as e:
logger.error(e)
return http.HttpResponseServerError('OAuth2.0认证失败')
pass