您当前的位置:首页 > IT编程 > python
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch | 异常检测 |

自学教程:Django之第三方平台QQ授权登录的实现

51自学网 2023-06-16 18:56:20
  python
这篇教程Django之第三方平台QQ授权登录的实现写得很实用,希望能帮到您。

环境准备

创建QQ互联应用

创建一个QQ互联应用,并获取到App ID和App Key。

QQ互联官网:https://connect.qq.com/

开发文档:https://wiki.connect.qq.com/

创建应用模块

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

python manage.py startapp oauth

在settings.py中注册应用

INSTALLED_APPS = [    # 'django.contrib.admin',    'django.contrib.auth',    'django.contrib.contenttypes',    'django.contrib.sessions',    'django.contrib.messages',    'django.contrib.staticfiles',    'apps.user',    'apps.oauth',]

在settings.py同级目录下的urls.py设置路由

url(r'^', include('apps.oauth.urls',namespace='oauth')),

定义QQ登录模型类

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

from django.db import modelsclass OAuthQQUser():    """QQ登录用户"""    user = models.ForeignKey('user.User', on_delete=models.CASCADE, verbose_name='用户')    openid = models.CharField(max_length=64, verbose_name='openid', db_index=True)    create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")    update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")    class Meta:        db_table = 'tb_oauth_qq'        verbose_name = 'QQ登录用户'        verbose_name_plural = verbose_name

执行迁移

执行迁移操作,生成QQ登录模型类对应的数据库表

python manage.py makemigrationspython manage.py migrate

QQLoginTool库

腾讯QQ互联平台没有Python SDK,但是可以使用第三方封装好的SDK包,QQLoginTool是一个第三方库,封装了对接QQ互联的请求操作,可用于快速实现QQ登录的一种工具包。

安装QQLoginTool

pip install QQLoginTool

API使用说明

导入

from QQLoginTool.QQtool import OAuthQQ

初始化OAuthQQ对象

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

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

login_url = oauth.get_qq_url()

通过Authorization Code获取Access Token

access_token = oauth.get_access_token(code)

通过Access Token获取OpenID

openid = oauth.get_open_id(access_token)

在settings.py配置QQ登录参数

QQ_CLIENT_ID = '1020343878'QQ_CLIENT_SECRET = 'Yu4123456LG0Yw53o'QQ_REDIRECT_URI = 'https://abc.com/oauth/callback'

QQ登录扫码页面

from django.urls import re_pathfrom . import viewsurlpatterns = [    re_path(r'^qq/login/$', views.QQAuthURLView.as_view()),]
from QQLoginTool.QQtool import OAuthQQfrom django import httpfrom django.conf import settingsfrom django.views import Viewfrom utils.response_code import RETCODE"""提供QQ登录页面网址https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=xxx&redirect_uri=xxx&state=xxx"""class QQAuthURLView(View):    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': 200 , 'msg': 'OK', 'login_url': login_url})

认证获取openid

1.用户在QQ登录成功后,QQ会将用户重定向到配置的回调网址,同时会传递一个Authorization Code2.拿到Authorization Code并完成OAuth2.0认证获取openid

注意:回调网址在申请QQ登录开发资质时进行配置

from django.urls import re_pathfrom . import viewsurlpatterns = [    re_path(r'^oauth/callback/$', views.QQAuthUserView.as_view()),]

使用code向QQ服务器请求,获取access_token

使用access_token向QQ服务器请求获取openid

"""用户扫码登录的回调处理"""class QQAuthUserView(View):    def get(self, request):        """Oauth2.0认证"""        # 提取code请求参数        code = request.GET.get('code')        if not code:            return http.HttpResponseBadRequest('缺少code')        # 创建oauth 对象        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,                        redirect_uri=settings.QQ_REDIRECT_URI)        try:            # 使用code向QQ服务器请求access_token            access_token = oauth.get_access_token(code)            # 使用access_token向QQ服务器请求openid            openid = oauth.get_open_id(access_token)        except Exception as e:            logger.error(e)            return http.HttpResponseServerError('OAuth2.0认证失败')        pass

openid的判断处理

openid是否绑定过用户

判断openid是否绑定过用户,只需要使用openid查询该QQ用户是否绑定过用户即可。

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

openid已绑定用户

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

try:    oauth_user = OAuthQQUser.objects.get(openid=openid)except OAuthQQUser.DoesNotExist:    # 如果openid没绑定用户    passelse:    # 如果openid已绑定用户,实现状态保持    qq_user = oauth_user.user    login(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

openid未绑定用户

openid属于用户隐私信息,在后续的绑定用户操作中前端会使用openid,因此需要将openid签名处理,避免暴露。

try:    oauth_user = OAuthQQUser.objects.get(openid=openid)except OAuthQQUser.DoesNotExist:    # 如果openid没绑定用户 generate_eccess_token:对openid签名    access_token = generate_eccess_token(openid)    context = {'access_token': access_token}    return render(request, 'oauthCallback.html', context)else:    qq_user = oauth_user.user    login(request, qq_user)    response = redirect(reverse('contents:index'))    response.set_cookie('username', qq_user.username, max_age=3600 * 24 * 15)    return response

oauthCallback.html中渲染access_token

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

openid签名处理

签名处理可以使用itsdangerous库,它是一个用于Python语言的库,提供了一些安全传输数据的工具类。其主要功能是在保证数据安全性的前提下,生成认证令牌、时间限制的令牌和加密/解密数据信息等。

安装itsdangerous

pip install itsdangerous

使用TimedJSONWebSignatureSerializer可以生成带有有效期的token

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

生成openid签名与校验

from itsdangerous import BadDatafrom itsdangerous import TimedJSONWebSignatureSerializer as Serializerfrom django.conf import settingsdef generate_eccess_token(openid):    """    对openid签名    :param openid: 用户openid    """    serializer = Serializer(settings.SECRET_KEY, expires_in=3600)    data = {'openid': openid}    token = serializer.dumps(data)    return token.decode()def check_access_token(access_token):    """    提取openid    :param access_token: 签名后的openid    """    serializer = Serializer(settings.SECRET_KEY, expires_in=3600)    try:        data = serializer.loads(access_token)    except BadData:        return None    else:        return data.get('openid')

openid绑定用户

openid绑定用户的过程类似于用户注册的业务逻辑

class QQAuthUserView(View):    """用户扫码登录的回调处理"""    def get(self, request):        """Oauth2.0认证"""        ......    def post(self, request):        """用户绑定openid"""        # 接收参数        mobile = request.POST.get('mobile')        password= request.POST.get('password')        sms_code_client = request.POST.get('sms_code')        access_token = request.POST.get('access_token')        # 判断参数是否齐全        if not all([mobile, password, sms_code_client]):            return http.HttpResponseBadRequest('缺少必传参数')        # 判断手机号是否合法        if not re.match(r'^1[3-9]/d{9}$', mobile):            return http.HttpResponseBadRequest('请输入正确的手机号码')        # 判断密码是否合格        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):            return http.HttpResponseBadRequest('请输入8-20位的密码')        # 判断短信验证码是否一致        redis_conn = get_redis_connection('code')        sms_code_server = redis_conn.get('sms_%s' % mobile)        if sms_code_server is None:            return render(request, 'oauthCallback.html', {'msg': '无效的短信验证码'})        if sms_code_client != sms_code_server.decode():            return render(request, 'oauthCallback.html', {'msg': '输入短信验证码有误'})        # 判断openid是否有效        openid = check_access_token(access_token)        if not openid:            return render(request, 'oauthCallback.html', {'msg': '无效的openid'})        # 保存注册数据        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 render(request, 'oauthCallback.html', {'msg': '用户名或密码错误'})        # 将用户绑定openid        try:            OAuthQQUser.objects.create(openid=openid, user=user)        except DatabaseError:            return render(request, 'oauthCallback.html', {'msg': '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

到此这篇关于Django之第三方平台QQ授权登录的实现的文章就介绍到这了,更多相关Django 第三方平台QQ授权登录内容请搜索51zixue.net以前的文章或继续浏览下面的相关文章希望大家以后多多支持51zixue.net!


Pycharm运行程序时,控制台输出PyDev
Python&nbsp;中将秒转换为小时、分钟和秒的示例代码
51自学网自学EXCEL、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。
京ICP备13026421号-1