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

c4468b3f4df77e96b0a416fa2a870fba.png

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

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

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

f8251edac78de5e2c61855bb1d258b09.png

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

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

90c61634deaf53cba55873574c2b1679.png

按照步骤获取Access_Token和Open_ID

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

24f959a59a549780afd0588ee5830c6b.png

接下来就是写后台程序了

首先,创建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)

c5271f26f63375d4e7f2e2e0eb4f5bf8.png

将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身份的处理流程图供参考

e3dff8c015cb696271228553aa5c8d24.png

65a094d6f9542ff623929f5cabc75c7f.png

标签:主域名

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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[1\],ClickHouse没有提供官方的Python接口驱动,但常用的第三方驱动接口是clickhouse_driver。你可以使用pip命令来安装clickhouse_driver,例如:pip install clickhouse_driver。安装完成后,你可以在Python代码中导入clickhouse_driver来使用它的功能。 然而,根据引用\[2\]中的错误信息,可能是由于clickhouse_driver的某个模块缺失导致的。具体来说,错误信息中提到了一个ModuleNotFoundError,即找不到名为'clickhouse_driver.varint'的模块。这可能是由于clickhouse_driver的版本不兼容或者安装过程中出现了问题。 为了解决这个问题,你可以尝试以下几个步骤: 1. 确保你已经正确安装了clickhouse_driver,并且版本与你的Python环境兼容。 2. 如果你已经安装了clickhouse_driver,可以尝试卸载并重新安装它,以确保安装过程中没有出现问题。 3. 如果问题仍然存在,你可以尝试查看clickhouse_driver的文档或者在相关的社区论坛上寻求帮助,以获取更详细的解决方案。 总之,根据引用\[1\]提供的信息,你可以使用clickhouse_driver作为ClickHouse的Python接口驱动,但根据引用\[2\]中的错误信息,可能需要进一步排查和解决问题。 #### 引用[.reference_title] - *1* *2* [Python使用ClickHouse实践与踩坑记](https://blog.csdn.net/xiaoyw/article/details/117692741)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [java sqlite配置和自定义函数](https://blog.csdn.net/dhe8356/article/details/101747960)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值