QQ登录流程
- 点击前端QQ登录的请求按钮,弹出扫码页面,用于手机扫码授权
- 如果之前登录过,那么就直接登录成功
- 如果是第一次使用QQ登录,会提示绑定之前的账号或者输入手机号
QQ登录流程准备的配置工作
1.进入到QQ互联,创建应用,需要审核,如果域名没有备案,审核不过
2.前端准备QQ登录图标点击事件
3.准备数据与Django框架进行交互,添加到setting文件 代码如下:
# QQ登录参数
# 我们申请的 客户端id
QQ_CLIENT_ID = 'xxxxxxxxxxxxx'
# 我们申请的 客户端秘钥
QQ_CLIENT_SECRET = 'xxxxxxxxxxxxx'
# 我们申请时添加的: 登录成功后回调的路径
QQ_REDIRECT_URI = 'xxxxxxxxxxxxx'
接入流程
- 1.根据oauth2.0获取code
- 2.根据code获取token
- 3.根据token获取openid
QQ登录的子应用和模型类
- 用户创建的账号和openid绑定到一起
- 创建自应用oauth,不要忘记注册应用
- 创建模型类OAuthQQUser继承BaseModel
- 执行数据库迁移命令
生成QQ跳转链接
- 生成QQ跳转链接,用户进行扫码登录,开发员拿到code
- 使用QQLoginTool完成此次功能
安装:pip install QQLoginTool
视图分析:
生成跳转的链接
前端 用户点击qq登录按钮,前端发送一个 axios请求 /qq/authorization/
后端
接收请求
逻辑 使用QQloginTool生成跳转链接
响应 返回链接 {"code":0,"login_url":'http://xxx.qq.com/fdfds'}
路由 get /qq/authorization/
代码:
class QQLoginURLView(View):
def get(self,request):
# 使用QQLoginTool生成跳转链接
from QQLoginTool.QQtool import OAuthQQ
# 初始化OAuthQQ对象
aouth = oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
redirect_uri=settings.QQ_REDIRECT_URI, state="xxx")
# 获取登录QQ扫码页面,扫码后得到code
login_url = oauth.get_qq_url()
# 返回响应
return JsonResponse({'code':0,'login_url':login_url })
注意:不要忘记将参数添加到setting文件中
获取code 根据code获取token 根据token获取openid
绑定账户和openid 绑定或者不绑定的逻辑
- 用户扫描完授权后,跳转到我们指定的回调地址并且参数里携带了code
- 通过前端页面分析oauth_callback.js的请求分析,我们会收到前端的请求,并且得到code
视图分析:
需求 获取code 根据code获取token 根据 token获取openid
前端:
发送axios请求 把code发送给后端 /oauth_callback/?code=fjdsskfklsdjl
后端
接收请求 接收参数 code
逻辑 根据code获取token 根据 token获取openid
响应
路由 get /oauth_callback/?code=fjdsskfklsdjl
代码:
class OauthView(View):
def get(self, request):
# 1获取code
code = request.GET.get('code')
print('code---->', code)
# 2根据code获取token
# 2.1导入
from QQLoginTool.QQtool import OAuthQQ
# 2.2初始化OAuthQQ对象
oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
redirect_uri=settings.QQ_REDIRECT_URI, state='xxx')
access_token = oauth.get_access_token(code)
# 3根据token获取openid
openid = oauth.get_open_id(access_token)
print('openid---->', openid)
# 4根据openid去数据库查询OAuthQQUser账号数据
try:
qquser = OAuthQQUser.objects.get(openid=openid)
except Exception as e:
print(e)
# 4.1如果不存在 捕获异常 走没有绑定的逻辑 去绑定页面
# 返回openid key:access_token
openid = generate_access_token(openid)
print('openid加密后---->', openid)
return JsonResponse({'code': 400, 'access_token': openid})
else:
# 4.2如果存在 正常返回数据 走登录保持
login(request, qquser.user)
response = JsonResponse({'code': 0, 'errmsg': 'ok'})
response.set_cookie('username', qquser.user.username)
return response
def post(self, request):
'''
需求 绑定帐号
前端:
用户 输入手机号 密码 短信验证码 发送axios请求 携带了openid
后端:
接收数据 校验
逻辑:
绑定 保存到数据库 登录状态保持
响应:
返回code0 直接去首页了
路由:
post /oauth_callback/
:param request:
:return:
'''
# 1接收请求
body = request.body
data_dict = json.loads(body)
# 2获取请求参数手机号密码短信验证码openid
password = data_dict.get('password')
mobile = data_dict.get('mobile')
sms_code = data_dict.get('sms_code')
openid = data_dict.get('access_token')
print('openid---->', openid)
# 对openid进行解密获取源数据
openid = check_access_token(openid)
# 验证参数
# 3根据手机号查询是否已经注册
try:
user = User.objects.get(mobile=mobile)
except Exception as e:
print(e)
# 5没有注册创建一个user对象绑定用户和openid
user = User.objects.create_user(username=mobile, mobile=mobile, password=password)
else:
if not user.check_password(password):
return JsonResponse({'code': 400, 'errmsg': '账号或者密码错误'})
try:
# 数据库操作 绑定user和openid
OAuthQQUser.objects.create(user=user, openid=openid)
except Exception as e:
print(e)
return JsonResponse({'code': 400, 'errmsg': '已经绑定'})
# 6状态保持
login(request, user)
response = JsonResponse({'code': 0, 'errmsg': 'ok'})
response.set_cookie('username', user.username)
# 7返回响应
return response