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互联的应用ID,最重要的是拿到APPID,创建应用的方法参考链接http://wiki.connect.qq.com/__trashed-2

申请时的网站域名即项目域名

网站回调域即用户通过扫码后需要跳转到的页面网址

QQ登录开发文档连接http://wiki.connect.qq.com/%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C_oauth2-0

此链接中的网站应用概述中 可以看到效果界面展示,然后点击进入网站开发流程,有5个下拉菜单,前两个是前端用的,后面三个是我们后端要用的

按照步骤获取Access_Token和Open_ID

下面是使用QQ登录的流程图

接下来就是写后台程序了

首先,创建QQ登录模型类,创建一个新的应用oauth,用来实现QQ第三方认证登录。总路由前缀 oauth/

终端进入到/meiduo_mall/apps目录下,使用命令python ../../manage.py startapp oauth 创建子应用oauth,记得创建完之后在settings文件中的INSTALLED_APPS中注册添加此应用,'oauth.apps.OauthConfig'

在meiduo/meiduo_mall/utils/models.py文件中创建模型类基类,用于增加数据新建时间和更新时间。(为什么要在公共的util中增加models呢,因为在模型类基类中创建的create_time,update_time在后面的商品类等中都会用到,方便调用)

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的表

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

from django.db import models

from meiduo_mall.utils.models import BaseModel

class 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)#openid其实就是我们当年申请QQ时,QQ服务器为我们生成的那个唯一标识

class Meta:

db_table = 'tb_oauth_qq'

verbose_name = 'QQ登录用户数据'

verbose_name_plural = verbose_name

接下来,终端进入到包含manage.py文件的meiduo_mall目录下,输入迁移命令

进行数据库迁移

python manage.py makemigrations

python manage.py migrate

第一步:点击QQ登录标签,跳转到QQ登录页面

settings配置文件中添加:

# QQ登录参数QQ_CLIENT_ID = '10147xxxx'

QQ_CLIENT_SECRET = 'c6ce949e04e12ecc909ae6a8b09b637c'

QQ_REDIRECT_URI = 'http://www.xxxx.xxxx:xxxx/oauth_callback.html'

QQ_STATE = '/'

新建oauth/utils.py文件,创建QQ登录辅助工具类

from urllib.parseimport urlencode, parse_qsfrom urllib.requestimport urlopenfrom itsdangerousimport TimedJSONWebSignatureSerializeras Serializer, BadDatafrom django.confimport settingsimport jsonimport loggingfrom .import constants

logger = logging.getLogger('django')classOAuthQQ(object):

""" QQ登录的工具类 """

"""构造方法接收所有的工具方法需要用到的参数"""

def__init__(self, client_id=None, client_secret=None, redirect_uri=None, state=None):

self.client_id = client_idor settings.QQ_CLIENT_ID#appidself.client_secret = client_secretor settings.QQ_CLIENT_SECRET#appkeyself.redirect_uri = redirect_urior settings.QQ_REDIRECT_URI

self.state = stateor settings.QQ_STATE# 用于保存登录成功后的跳转页面路径defget_qq_login_url(self):

"""

获取qq登录的网址

:return: url网址

"""

params = {

'response_type': 'code',#此值固定为code,作用是告诉QQ服务器,此用户拿着QQ在扫码,是为了得到一个code,有code才能得到Access_Token

'client_id': self.client_id,#申请QQ登录成功后,分配给应用的appid'redirect_uri': self.redirect_uri,#网站回调域的网址,必须是注册appid时填写的主域名下的地址,建议设置为网站首页或网站的用户中心。注意需要将url进行URLEncode'state': self.state,#就是next,# QQ登录成功后回去的地方

'scope':'get_user_info',#请求用户授权,手机正在扫码的用户,# 标识扫码最终为了获取QQ用户的信息(openid)}#拼接QQ扫码登录连接login_url='https://graph.qq.com/oauth2.0/authorize?' + urlencode(params)

returnlogin_url

在oauth/views.py中实现视图

# url(r'^qq/authorization/$', views.QQAuthURLView.as_view()),

classQQAuthURLView(APIView):

"""

获取QQ登录的url

"""

defget(self, request):

"""

提供用于qq登录的url

"""

#获取到next参数,实现将来从哪里进入的登录界面,QQ登录成功后,就回到哪里

next = request.query_params.get('next')

oauth = OAuthQQ(state=next)#生成QQ扫码登录连接(逻辑)login_url = oauth.get_qq_login_url()return Response({'login_url': login_url})子应用中的urls中添加路由

from django.conf.urls import url

from . import views

urlpatterns=[

url(r'^qq/authorization/$', views.QQAuthURLView.as_view()),

]

主业务逻辑的urls中添加子应用路由

urlpatterns = [

#QQ登录

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

]

urllib使用说明

在后端接口中,我们需要向QQ服务器发送请求,查询用户的QQ信息,Python提供了标准模块urllib可以帮助我们发送http请求。

urllib.parse.urlencode(query)

将query字典转换为url路径中的查询字符串

urllib.parse.parse_qs(qs)

将qs查询字符串格式数据转换为python的字典

urllib.request.urlopen(url, data=None)

发送http请求,如果data为None,发送GET请求,如果data不为None,发送POST请求

返回response响应对象,可以通过read()读取响应体数据,需要注意读取出的响应体数据为bytes类型

第二步:用户扫码登录的回调处理

用户在QQ登录成功后,QQ会将用户重定向回我们配置的回调callback网址,即我们申请QQ登录开发资质时配置的回调地址;

第三步:绑定用户身份接口

业务逻辑:

用户需要填写手机号、密码、图片验证码、短信验证码

如果用户未在美多商城注册过,则会将手机号作为用户名为用户创建一个美多账户,并绑定用户

如果用户已在美多商城注册过,则检验密码后直接绑定用户

注:以下代码合并二三步

新建oauth/serializers.py文件

from rest_framework importserializersfrom .utils importOAuthQQfrom django_redis importget_redis_connectionfrom users.models importUserfrom .models importOAuthQQUserclassQQAuthUserSerializer(serializers.Serializer):"""QQ登录创建用户序列化器"""

#是外界的request.data传过来的注册时的请求体数据

access_token = serializers.CharField(label='操作凭证')

mobile= serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$')

password= serializers.CharField(label='密码', max_length=20, min_length=8)

sms_code= serializers.CharField(label='短信验证码')defvalidate(self, data):#检验access_token

access_token = data['access_token']#获取身份凭证

openid =OAuthQQ.check_save_user_token(access_token)if notopenid:raise serializers.ValidationError('无效的access_token')#将openid放在校验字典中,后面会使用

data['openid'] =openid#检验短信验证码

mobile = data['mobile']

sms_code= data['sms_code']

redis_conn= get_redis_connection('verify_codes')

real_sms_code= redis_conn.get('sms_%s' %mobile)if real_sms_code.decode() !=sms_code:raise serializers.ValidationError('短信验证码错误')#如果用户存在,检查用户密码

try:

user= User.objects.get(mobile=mobile)exceptUser.DoesNotExist:pass

else:

password= data['password']if notuser.check_password(password):raise serializers.ValidationError('密码错误')#将认证后的user放进校验字典中,后续会使用

data['user'] =userreturndatadefcreate(self, validated_data):#获取校验的用户

user = validated_data.get('user')if notuser:#用户不存在,新建用户

user =User.objects.create_user(

username=validated_data['mobile'],

password=validated_data['password'],

mobile=validated_data['mobile'],

)#将用户绑定openid

OAuthQQUser.objects.create(

openid=validated_data['openid'],

user=user

)#返回用户数据

return user

新建oauth/exceptions.py文件

classQQAPIException(Exception):"""自定义QQ异常"""

pass

新建oauth/constants.py文件

#QQ登录保存用户数据的token有效期

SAVE_QQ_USER_TOKEN_EXPIRES=600

使用itsdangerous生成凭据access_token,itsdangerous模块的参考资料连接http://itsdangerous.readthedocs.io/en/latest/

需要安装itsdangerous

pip install itsdangerous

使用TimedJSONWebSignatureSerializer可以生成带有有效期的token在oauth/utils.py文件OAuthQQ辅助类中添加方法:

from urllib.parse import urlencode,parse_qs

from urllib.request import urlopen

from .exceptions import QQAPIException

import json

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer, BadData

from .exceptions import QQAPIException

from . import constants

import logging

# 日志记录器

logger = logging.getLogger('django')

def  get_access_token(self, code):

"""获取access_token"""

# 准备url

url = 'https://graph.qq.com/oauth2.0/token?'

# 准备参数

params = {

'grant_type':'authorization_code',

'client_id':self.client_id,

'client_secret':self.client_secret,

'code':code,

'redirect_uri':self.redirect_uri

}

# 拼接地址

url += urlencode(params)

try:

# 使用code向QQ服务器发送请求获取access_token

response = urlopen(url)

# 获取响应的二进制

response_data = response.read()

# 将response_data转成字符串

# access_token=FE04************************CCE2&expires_in=7776000&refresh_token=88E4************************BE14

response_str = response_data.decode()

# 将response_str转成字典

response_dict = parse_qs(response_str)

# 提取access_token

# response_dict.get('access_token') == [FE04************************CCE2]

access_token = response_dict.get('access_token')[0]

except  Exception as e:

logger.error(e)

raise QQAPIException('获取access_token失败')

return access_token

def  get_openid(self, access_token):

"""

使用access_token向QQ服务器请求openid

:param access_token: 上一步获取的access_token

:return: open_id

"""

# 准备url

url = 'https://graph.qq.com/oauth2.0/me?access_token=' + access_token

# 美多向QQ服务器发送请求获取openid

response_str = ''

try:

response = urlopen(url)

response_str = response.read().decode()

# 返回的数据 callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} )\n;

response_dict = json.loads(response_str[10:-4])

# 获取openid

openid = response_dict.get('openid')

except Exception as e:

# 如果有异常,QQ服务器返回 "code=xxx&msg=xxx"

data = parse_qs(response_str)

logger.error(e)

raise QQAPIException('code=%s msg=%s' % (data.get('code'), data.get('msg')))

return openid

@staticmethod

def generate_save_user_token(openid):

"""

生成保存用户数据的token

:param openid: 用户的openid

:return: token

"""

serializer = Serializer(settings.SECRET_KEY, expires_in=constants.SAVE_QQ_USER_TOKEN_EXPIRES)

data = {'openid': openid}

token = serializer.dumps(data)

return token.decode()

@staticmethod

def check_save_user_token(token):

"""

检验保存用户数据的token

:param token: token

:return: openid or None

"""

serializer = Serializer(settings.SECRET_KEY, expires_in=constants.SAVE_QQ_USER_TOKEN_EXPIRES)

try:

data = serializer.loads(token)

except BadData:

return None

else:

return data.get('openid')

在oauth/views.py中实现视图:

from rest_framework.response import Response

from rest_framework import status

from rest_framework_jwt.views import api_settings

from rest_framework.generics import GenericAPIView

from .utils import OAuthQQ

from .exceptions import QQAPIException

from .models import OAuthQQUser

from . import serializers

# url(r'^qq/user/$', views.QQAuthUserView.as_view()),?

class QQAuthUserView(GenericAPIView):

"""用户扫码登录的回调处理"""

# 指定序列化器

serializer_class = serializers.QQAuthUserSerializer

def get(self, request):

# 提取code请求参数

code = request.query_params.get('code')

if not code:

return Response({'message':'缺少code'}, status=status.HTTP_400_BAD_REQUEST)

# 创建QQ登录的工具对象

oauth = OAuthQQ()

try:

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

access_token = oauth.get_access_token(code)

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

openid = oauth.get_openid(access_token)

except  QQAPIException:

return Response({'message':'QQ服务异常'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)

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

try:

oauth_user = OAuthQQUser.objects.get(openid=openid)

except OAuthQQUser.DoesNotExist:

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

access_token_openid = OAuthQQ.generate_save_user_token(openid)

return Response({'access_token':access_token_openid})

else:

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

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER

jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

# 获取关联openid的user

user = oauth_user.user

payload = jwt_payload_handler(user)

token = jwt_encode_handler(payload)

# 向前端响应token, user_id,username

return Response({

'token':token,

'user_id':user.id,

'username':user.username

})

def post(self, request):

"""给openid绑定用户数据"""

# 获取序列化器:注册的数据都在POST请求的请求体里面

serializer = self.get_serializer(data=request.data)

# 开启校验

serializer.is_valid(raise_exception=True)

# 保存校验的数据 : create会返回user

user = serializer.save()

# 生成JWT token 响应

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER

jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

payload = jwt_payload_handler(user)

token = jwt_encode_handler(payload)

# 向前端响应token, user_id,username

return Response({

'token': token,

'user_id': user.id,

'username': user.username

})

在oauth/urls中 添加路由

urlpatterns=[

# 获取QQ扫码登录连接

url(r'^qq/authorization/$', views.QQAuthURLView.as_view()),

# 获取QQ登录用户信息(code,access_token, openid)

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

]

最后再上一张绑定QQ身份的处理流程图供参考

标签:主域名

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com

特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

read.html5.qq.com,如何通过第三方QQ登录网站首页相关推荐

  1. 分别嵌入 新浪微博、QQ、微信 做第三方授权登录 获取到头像 昵称等信息

    下面提到的这三种 授权登录 是分别嵌入,不是 share sdk 或者友盟 其它的. 一.下载sdk 地址 1.新浪微博 新浪微博SDK 下载 2.QQ  QQ SDK 下载 3.微信 微信SDK 二 ...

  2. 手机qq协议做的第三方qq软件

    前段时间没事做,就把网上爆出来的qq的手机协议给整理了下,然后试着调用,总之就是把这些弄一起了,做了这么 一个qq的第三方软件. 还研究了下那个小黄鸡,把它给结合到这个软件里,添加了一些qq上没有的自 ...

  3. Django 实现第三方账号登录网站

    这里我们使用 django-allauth 模块来实现第三方账号验证登录,官方文档如下:https://django-allauth.readthedocs.io/en/latest/ . 安装 dj ...

  4. Java 实现第三方 QQ 账号登录

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | uidaima.com/blog/472561 ...

  5. 使用ShareSDK完成第三方(QQ、微信、微博)登录和分享

    这几天遇到一个需求:做第三方登录和分享.遇到了一些坑,把整个过程整理记录下来,方便他人,同时也捋一下思路. 当时考虑过把每个平台的SDK下载下来,一个一个弄,一番取舍后决定还是用ShareSDK.这里 ...

  6. android qq分组展开,Android仿qq分组管理的第三方库

    本文实例为大家分享了Android仿qq分组管理的第三方库,供大家参考,具体内容如下 下面先看效果 我们点击展开与折叠分组的功能在库里面是已经封装好的,只能把它已入到项目中,就可以直接用了,十分的方便 ...

  7. python的flask实现第三方登录怎么写_关于qq和新浪微博的第三方登陆|python|flask

    前些日子研究了一下qq和新浪微博的第三方登陆的东西,发现其实难度并不大.来给大家分享一下我的经验和流程. 不论是qq还是新浪微博的第三方登陆都是用了Oauth2.0授权流程,唯一不同的是qq多了一个o ...

  8. android登录操作代码,Android Studio实现第三方QQ登录操作代码

    来看看效果图吧 实现QQ登录了, 新建一个项目工程 ,然后把我们刚才下载的SDK解压将jar文件夹中的jar包拷贝到我们的项目libs中 导入一个下面架包就可以 项目结构如下 打开我们的清单文件And ...

  9. Oauth2.0 QQ微信微博实现第三方登陆

    一.写在前面 目前对于大多数的App或Web网站都支持有第三方登陆这个功能,用户可使用 QQ/ 微信/ 微博 帐号快速登录你的网站,降低注册门槛,为你的网站带来海量新用户.最近在新项目上刚好用到了,在 ...

最新文章

  1. 刚才遇到了关于C#使用外部DLL函数上的char*的问题。
  2. 9.逆向-函数调用约定
  3. 【嵌入式开发】ARM 代码搬移 ( ARM 启动流程 | 代码搬移 起点 终点 | 链接地址 | 汇编代码 )
  4. 告警系统邮件引擎、运行告警系统
  5. boost.asio系列——socket编程
  6. SQL Server 表变量和临时表的区别
  7. django(7)modelform操作及验证、ajax操作普通表单数据提交、文件上传、富文本框基本使用...
  8. 大数据WEB阶段 后台和页面之间传递日期格式数据的400问题
  9. web.xml详细介绍
  10. 道闸系统服务器价格,小区道闸系统价格服务客户
  11. 协议圣经 四 rtspclient
  12. WSUS补丁服务器部署详细 利用WSUS部署更新程序
  13. 蓝桥杯 ADV-165算法提高 超级玛丽(动态规划、递推)
  14. mariaDB数据库存放路径修改配置问题
  15. Implement Trie (Prefix Tree)
  16. FontLab v7 7.2.0 字体编辑器
  17. 利用sublime3 + xmapp使用服务器调试
  18. html求相关系数,关于pearson相关系数的意义
  19. java opencv 实现换脸
  20. cmnet和cmwap的访问

热门文章

  1. 正品,买东西 去哪里
  2. java程序员首次使用mac M1
  3. PDF转ePub选择人工转换的原因
  4. 阿里云 centos安装oracle 11g 完全图解
  5. 开源项目—FLutter/iOS/Android编写的三个计算器APP
  6. 一文读懂DEFI借贷以及清算的含义
  7. cadence导入dxf文件_PCB原创|cadence allegro导入DXF文件操作步骤
  8. css如何把北京图片变小,css怎么把图片缩小
  9. 计算机函数求最大值怎么设置,高中数学函数的最大值和最小值怎么求
  10. oracle的ofs,OFS_Oracle11g_Windows2008R2