025、QQ互联

news/2025/1/13 2:35:52/

一、QQ登录开发文档

QQ登录:即我们所说的第三方登录,是指用户可以不在本项目中输入密码,而直接通过第三方的验证,成功登录本项目。

1. QQ互联开发者申请步骤

若想实现QQ登录,需要成为QQ互联的开发者,审核通过才可实现。

  • 相关连接:http://wiki.connect.qq.com/%E6%88%90%E4%B8%BA%E5%BC%80%E5%8F%91%E8%80%85

2. QQ互联应用申请步骤

成为QQ互联开发者后,还需创建应用,即获取本项目对应与QQ互联的应用ID。

  • 相关连接:http://wiki.connect.qq.com/__trashed-2

3. 网站对接QQ登录步骤

QQ互联提供有开发文档,帮助开发者实现QQ登录。

  • 相关连接:http://wiki.connect.qq.com/%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C_oauth2-0

4. QQ登录流程分析

1、客户端点击QQ登陆按钮,请求商城得到扫码登陆链接,

2、客户端打开扫码登陆链接,请求QQ互联返回客户端扫码登陆页面,

3、客户端扫码,请求QQ互联返回Authorization Code,

4、商城使用Authorization Code请求QQ互联得到access_token,

5、商城使用access_token请求QQ互联得到openid.

二、定义QQ登录模型类

QQ登录成功后,我们需要将QQ用户和美多商场用户关联到一起,方便下次QQ登录时使用,所以我们选择使用MySQL数据库进行存储。

1. 定义模型类基类

为了给项目中模型类补充数据创建时间和更新时间两个字段,我们需要定义模型类基类。 在meiduo_mall.utils/models.py文件中创建模型类基类。

from django.db import modelsclass 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登录模型类

创建一个新的应用oauth,用来实现QQ第三方认证登录。

# oauth

url(r'^oauth/', include('oauth.urls')),

在oauth/models.py中定义QQ身份(openid)与用户模型类User的关联关系

from django.db import modelsfrom meiduo_mall.utils.models import BaseModel
# Create your models here.sclass OAuthQQUser(BaseModel):"""QQ登录用户数据"""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. 迁移QQ登录模型类

$ python manage.py makemigrations $ python manage.py migrate

三、QQ登录工具QQLoginTool

1. QQLoginTool介绍

  • 该工具封装了QQ登录时对接QQ互联接口的请求操作。可用于快速实现QQ登录。

2. QQLoginTool安装

pip install QQLoginTool

3. QQLoginTool使用说明

1.导入

from QQLoginTool.QQtool import OAuthQQ

2.初始化OAuthQQ对象

oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI, state=next)

3.获取QQ登录扫码页面,扫码后得到Authorization Code

login_url = oauth.get_qq_url()

4.通过Authorization Code获取Access Token

access_token = oauth.get_access_token(code)

5.通过Access Token获取OpenID

openid = oauth.get_open_id(access_token)

四、OAuth2.0认证获取openid

待处理业务逻辑

# 提取code请求参数

# 使用code向QQ服务器请求access_token

# 使用access_token向QQ服务器请求openid

# 使用openid查询该QQ用户是否在美多商城中绑定过用户

# 如果openid已绑定美多商城用户,直接生成JWT token,并返回

# 如果openid没绑定美多商城用户,创建用户并绑定到openid

1. 获取QQ登录扫码页面

1.请求方式

选项

方案

请求方法

GET

请求地址

/qq/authorization/

2.请求参数:查询参数

参数名

类型

是否必传

说明

next

string

用于记录QQ登录成功后进入的网址

3.响应结果:JSON

字段

说明

code

状态码

errmsg

错误信息

login_url

QQ登录扫码页面链接

4.后端逻辑实现

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})

5.QQ登录参数

QQ_CLIENT_ID = '101518219'

QQ_CLIENT_SECRET = '418d84ebdc7241efb79536886ae95224'

QQ_REDIRECT_URI = 'http://www.meiduo.site:8000/oauth_callback'

2. 接收Authorization Code

提示:

  • 用户在QQ登录成功后,QQ会将用户重定向到我们配置的回调网址。
  • 在QQ重定向到回调网址时,会传给我们一个Authorization Code。
  • 我们需要拿到Authorization Code并完成OAuth2.0认证获取openid。
  • 在本项目中,我们申请QQ登录开发资质时配置的回调网址为:

http://www.meiduo.site:8000/oauth_callback

  • QQ互联重定向的完整网址为:

http://www.meiduo.site:8000/oauth_callback/?code=AE263F12675FA79185B54870D79730A7&state=%2F

 

class QQAuthUserView(View):"""用户扫码登录的回调处理"""def get(self, request):"""Oauth2.0认证"""# 接收Authorization Codecode = request.GET.get('code')if not code:return http.HttpResponseForbidden('缺少code')pass

子应用路由

url(r'^oauth_callback/$', views.QQAuthUserView.as_view()),

3. OAuth2.0认证获取openid

  1. 使用code向QQ服务器请求access_token
  2. 使用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_tokenaccess_token = oauth.get_access_token(code)# 使用access_token向QQ服务器请求openidopenid = oauth.get_open_id(access_token)except Exception as e:logger.error(e)return http.HttpResponseServerError('OAuth2.0认证失败')pass

4. 本机绑定www.meiduo.site域名

编辑 /etc/hosts

sudo vim /etc/hosts

 

编辑 C:\Windows\System32\drivers\etc\hosts

五、openid是否绑定用户的处理

1. 判断openid是否绑定过用户

使用openid查询该QQ用户是否在美多商城中绑定过用户。

try:oauth_user = OAuthQQUser.objects.get(openid=openid)
except OAuthQQUser.DoesNotExist:# 如果openid没绑定美多商城用户pass
else:# 如果openid已绑定美多商城用户pass

2. openid已绑定用户的处理

如果openid已绑定美多商城用户,直接生成状态保持信息,登录成功,并重定向到首页。

try:oauth_user = OAuthQQUser.objects.get(openid=openid)
except OAuthQQUser.DoesNotExist:# 如果openid没绑定美多商城用户pass
else:# 如果openid已绑定美多商城用户# 实现状态保持qq_user = oauth_user.userlogin(request, qq_user)# 响应结果# 获取界面跳转来源next = request.GET.get('state')response = redirect(next)# 登录时用户名写入到cookie,有效期15天response.set_cookie('username', qq_user.username, max_age=3600 * 24 * 15)return response

3. openid未绑定用户的处理

  • 为了能够在后续的绑定用户操作中前端可以使用openid,在这里将openid签名后响应给前端。
  • openid属于用户的隐私信息,所以需要将openid签名处理,避免暴露。
try:oauth_user = OAuthQQUser.objects.get(openid=openid)
except OAuthQQUser.DoesNotExist:# 如果openid没绑定美多商城用户access_token = generate_eccess_token(openid)context = {'access_token': access_token}return render(request, 'oauth_callback.html', context)
else:# 如果openid已绑定美多商城用户# 实现状态保持qq_user = oauth_user.userlogin(request, qq_user)# 响应结果# 获取界面跳转来源next = request.GET.get('state')response = redirect(next)# 登录时用户名写入到cookie,有效期15天response.set_cookie('username', qq_user.username, max_age=3600 * 24 * 15)return response

oauth_callback.html中渲染access_token

<input v-model="access_token" type="hidden" name="access_token" value="{{ access_token }}">

4. 补充itsdangerous的使用

  • itsdangerous模块的参考资料链接 http://itsdangerous.readthedocs.io/en/latest/

安装:pip install itsdangerous

  • TimedJSONWebSignatureSerializer的使用
    • 使用TimedJSONWebSignatureSerializer可以生成带有有效期的token
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from django.conf import settings# serializer = Serializer(秘钥, 有效期秒)
serializer = Serializer(settings.SECRET_KEY, 300)
# serializer.dumps(数据), 返回bytes类型
token = serializer.dumps({'mobile': '18512345678'})
token = token.decode()# 检验token
# 验证失败,会抛出itsdangerous.BadData异常
serializer = Serializer(settings.SECRET_KEY, 300)
try:data = serializer.loads(token)
except BadData:return None

补充:openid签名处理

oauth.utils.py

def generate_eccess_token(openid):"""签名openid:param openid: 用户的openid:return: access_token"""serializer = Serializer(settings.SECRET_KEY, expires_in=constants.ACCESS_TOKEN_EXPIRES)data = {'openid': openid}token = serializer.dumps(data)return token.decode()

六、openid绑定用户实现

类似于用户注册的业务逻辑

  • 当用户输入的手机号对应的用户已存在
    • 直接将该已存在用户跟openid绑定
  • 当用户输入的手机号对应的用户不存在
    • 新建一个用户,并跟openid绑定
class QQAuthUserView(View):"""用户扫码登录的回调处理"""def get(self, request):"""Oauth2.0认证"""......def post(self, request):"""美多商城用户绑定到openid"""# 接收参数mobile = request.POST.get('mobile')pwd = request.POST.get('password')sms_code_client = request.POST.get('sms_code')access_token = request.POST.get('access_token')# 校验参数# 判断参数是否齐全if not all([mobile, pwd, sms_code_client]):return http.HttpResponseForbidden('缺少必传参数')# 判断手机号是否合法if not re.match(r'^1[3-9]\d{9}$', mobile):return http.HttpResponseForbidden('请输入正确的手机号码')# 判断密码是否合格if not re.match(r'^[0-9A-Za-z]{8,20}$', pwd):return http.HttpResponseForbidden('请输入8-20位的密码')# 判断短信验证码是否一致redis_conn = get_redis_connection('verify_code')sms_code_server = redis_conn.get('sms_%s' % mobile)if sms_code_server is None:return render(request, 'oauth_callback.html', {'sms_code_errmsg':'无效的短信验证码'})if sms_code_client != sms_code_server.decode():return render(request, 'oauth_callback.html', {'sms_code_errmsg': '输入短信验证码有误'})# 判断openid是否有效:错误提示放在sms_code_errmsg位置openid = check_access_token(access_token)if not openid:return render(request, 'oauth_callback.html', {'openid_errmsg': '无效的openid'})# 保存注册数据try:user = User.objects.get(mobile=mobile)except User.DoesNotExist:# 用户不存在,新建用户user = User.objects.create_user(username=mobile, password=pwd, mobile=mobile)else:# 如果用户存在,检查用户密码if not user.check_password(pwd):return render(request, 'oauth_callback.html', {'account_errmsg': '用户名或密码错误'})# 将用户绑定openidtry:OAuthQQUser.objects.create(openid=openid, user=user)except DatabaseError:return render(request, 'oauth_callback.html', {'qq_login_errmsg': 'QQ登录失败'})# 实现状态保持login(request, user)# 响应绑定结果next = request.GET.get('state')response = redirect(next)# 登录时用户名写入到cookie,有效期15天response.set_cookie('username', user.username, max_age=3600 * 24 * 15)return response

 


http://www.ppmy.cn/news/866064.html

相关文章

QQ API

QQ API设计说明书目录一、引言 31.1 编写目的 31.2 更新时间 3二、总体设计 3三、注册的系统消息 33.1 WM_QQAPI_REGISTER 33.2 WM_QQAPI_REGISTER_RESP 43.3 WM_QQAPI_AVAILABLE 4四、从设备到QQ的自定义事件 54.1 EVENT_QQAPI_SET_AUDIODEVICE …

本地部署 Stable Diffusion XL Gradio Demo WebUI

StableDiffusion XL Gradio Demo WebUI 0. 先展示几张 StableDiffusion XL 生成的图片1. 什么是 Stable Diffusion XL Gradio Demo WebUI2. Github 地址3. 安装 Miniconda34. 创建虚拟环境5. 安装 Stable Diffusion XL Gradio Demo WebUI6. 启动 Stable Diffusion XL Gradio De…

Vue3通透教程【十五】补充TS开发环境搭建问题

文章目录 &#x1f31f; 写在前面&#x1f31f; Node中搭建TS开发环境&#x1f31f; 验证环境&#x1f31f; 写在最后 &#x1f31f; 写在前面 专栏介绍&#xff1a; 凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章&#xff0c;应粉丝要求开始更新 Vue3 的相关技术文章&#…

跑步机 使用心得

我是办公工作的一员&#xff0c;每天除了吃饭休息外&#xff0c;大多时间都是面对电脑&#xff0c;于是和家里 商量准备在家里添一件健身器材。在淘宝上搜寻和在朋友的建议下&#xff0c;最终选择澳瑞特的跑 步机。选择奥瑞特&#xff0c;就是看中在我们当地就有实体店和售后…

阿里巴巴B2B 3月全国招聘会

招聘会信息如下: 时间

安徽省大数据比赛——数据可视化实战

第四部分&#xff1a;可视化&#xff08;15分&#xff09; 近些年空气污染在我国很多地区非常严重&#xff0c;其中PM2.5作为衡量空气质量的一个重要指标&#xff0c;当前数据为2018年12月份1号-10号全国大部分城市的站点检测数据。接下来我们将这些数据进行可视化来看下PM2.5…

算法刷题Day 38 动态规划理论基础+斐波那契数+爬楼梯

Day 38 动态规划 理论基础 动态规划的解题步骤&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 斐波那契数 很基础 class Solution { public:int fib(int n) {int a 0, b 1;while (n--…

QT+MySql

QT+MySql 安装驱动 sudo apt-get update sudo apt-get install mysql-server 安装QMYSQL驱动程序。 sudo apt-get install libqt5sql5-mysql命令操作 登录 sudo mysql -u root -p查看所有数据库 SHOW DATABASES;创建一个数据库 CREATE DATABASE video_file;选择数…