【愚公系列】2022年01月 Django商城项目13-登录界面-QQ登录功能实现
前言
1.QQ互联开发者申请
若想实现QQ登录,需要成为QQ互联的开发者,审核通过才可实现
相关连接:https://connect.qq.com/
第一步:首先使用qq登录
第二步:注册个人应用
注册成功后如下
2.QQ互联应用申请
成为QQ互联开发者后,还需创建应用,即获取本项目对应与QQ互联的应用ID。
相关连接:https://connect.qq.com/manage.html#/appcreate/web
3.网站对接QQ登录
QQ互联提供有开发文档,帮助开发者实现QQ登录。
相关连接:http://wiki.connect.qq.com/%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C_oauth2-0
一、django实际对接流程
1.创建抽象模型类
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的表
2.创建QQ用户模型类
from django.db import models from utils.models import BaseModel class OAuthQQUser(BaseModel): """QQ登录用户数据""" # ForeignKey 我们使用了 其他子应用的模型 # 我们采用 '子应用名.模型类名' user = models.ForeignKey('users.User', on_delete=models.CASCADE, verbose_name='用户') openid = models.CharField(max_length=64, verbose_name='openid', db_index=True) class Meta: db_table = 'tb_oauth_qq' verbose_name = 'QQ登录用户数据' verbose_name_plural = verbose_name
3.注册应用
# Application references # https://docs.djangoproject.com/en/2.1/ref/settings/#std:setting-INSTALLED_APPS INSTALLED_APPS = [ 'app', # Add your apps here to enable them 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app.users', 'app.oauth', ]
4.配置QQ登录信息
# QQ登陆相关的 QQ_CLIENT_ID = '填写自己的' QQ_CLIENT_SECRET = '填写自己的' QQ_REDIRECT_URI = '填写自己的'
5.登录返回的URL地址和回调信息
from django.shortcuts import render from QQLoginTool.QQtool import OAuthQQ from DJ_MeiDuo import settings from django import http from django.views import View # Create your views here. class OauthQQURLView(View): def get(self,request): #1.创建实例对象 state = 'test' qqoauth = OAuthQQ( client_secret=settings.QQ_CLIENT_SECRET, client_id=settings.QQ_CLIENT_ID, redirect_uri=settings.QQ_REDIRECT_URI, state=state ) #2.调用方法 login_url = qqoauth.get_qq_url() return http.JsonResponse({'login_url':login_url}) class OauthQQUserView(View): def get(self,request): # 1.获取code code = request.GET.get('code') if code is None: return render(request,'oauth_callback.html',context={'errmsg':'没有获取到指定参数'}) # 2. 通过读取文档将code转换为token qqoauth = OAuthQQ( client_secret=settings.QQ_CLIENT_SECRET, client_id=settings.QQ_CLIENT_ID, redirect_uri=settings.QQ_REDIRECT_URI ) token = qqoauth.get_access_token(code) #3.通过token换取openid openid = qqoauth.get_open_id(token) # 4. 我们需要根据 openid 进行数据的查询 try: qquser = OAuthQQUser.objects.get(openid=openid) except OAuthQQUser.DoesNotExist: # 如果没有同样的openid,则说明用户没有绑定过 # 对openid进行一个加密的处理 openid_access_token = generate_access_token(openid) return render(request,'oauth_callback.html',context={'openid_access_token':openid_access_token}) else: # 如果有同样的openid,则说明用户绑定过 # 则直接登陆 response = redirect(reverse('contents:index')) #1. 设置登陆状态 login(request,qquser.user) #2.设置cookie信息 response.set_cookie('username',qquser.user.username,max_age=14*24*3600) return response # return render(request,'oauth_callback.html') def post(self,request): # 1.先接收数据 data = request.POST # 2.获取数据 mobile = data.get('mobile') password = data.get('pwd') sms_code = data.get('sms_code') access_token = data.get('access_token') # 3.验证数据 # 省略 # 4.access_token( 加密之后的openid)解密 openid = check_access_token(access_token) # 5.根据手机号进行用户信息的判断 try: user = User.objects.get(mobile=mobile) except User.DoesNotExist: # 如果此手机号之前没有注册过,则重新创建用户 user = User.objects.create_user( username=mobile, password=password, mobile=mobile ) else: # 如果此手机号之前注册过,绑定前要验证密码 if not user.check_password(password): return http.HttpResponseBadRequest('密码错误') # 则和用户进行绑定, qquser = OAuthQQUser.objects.create( user=user, openid=openid ) # 6.设置登陆的状态 login(request,user) # 7.设置cookie信息 response = redirect(reverse('contents:index')) response.set_cookie('username',user.username,max_age=14*24*3600) # 8.跳转指定页面 return response
加解密方法的封装
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer from app.oauth.constants import OPENID_TOKEN_EXPIRE_TIME from DJ_MeiDuo import settings def generate_access_token(openid): #1. 创建实例对象 s = Serializer(secret_key=settings.SECRET_KEY,expires_in=OPENID_TOKEN_EXPIRE_TIME) #2.组织数据 data = { 'openid':openid } #3.加密处理 token = s.dumps(data) #4. 返回 return token.decode() def check_access_token(token): #1.创建实例对象 s = Serializer(secret_key=settings.SECRET_KEY, expires_in=OPENID_TOKEN_EXPIRE_TIME) #2. 解密数据 result = s.loads(token) # script = {'openid':'xxxx'} #3.返回数据 return result['openid']
6.回调页面逻辑功能实现