django_pycharm社区版4_google_auth2

本文详细介绍如何在Django项目中集成Google Authenticator,实现双因素认证。从环境搭建、包导入、代码修改到测试验证,全面覆盖。适用于希望增强应用安全性、了解双因素认证原理的开发者。


验证django_google_auth用户认证。Google Authenticator是个开源项目,谷歌身份验证器实现原理类似于 QQ 令牌,不依赖于网络,30秒更新一次。

前期准备

导入包

pip install django-google-auth2

复制文件到项目app目录下

这3个文件复制到当前appa目录下,我们的业务方法会用到它里面的逻辑。
在这里插入图片描述

修改代码

settings.py文件

注入django-google-auth2包到项目

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp1',
    'rest_framework',
    'rest_framework.authtoken',
    'rest_framework_jwt',
    'django_google_auth2',
]

models.py文件

google动态认证用要数据库,所以要在models.py作一些处理,它用到两个类:

from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.


class UserProfile(AbstractUser):
    #用户信息表,直接继承AbstractUser,根据需要自己修改;
    pass


用于存储秘钥的表,根用户表通过id关联
class Google2Auth(models.Model):
    """GoogleAuth"""
    user = models.OneToOneField(UserProfile, on_delete=models.CASCADE)
    key = models.CharField(verbose_name="Google秘钥", max_length=128)

gauth.py文件

这里包括新建用户,绑定用户和认证用户三个类,实现我们的业务逻辑功能。

from drf_dynamic_fields import DynamicFieldsMixin
from rest_framework.views import APIView
from . import models
from rest_framework.response import Response
from rest_framework import serializers
from rest_framework_jwt.settings import api_settings
import base64
import codecs
import random
import re
import pyotp
from . import googletotp
from django.shortcuts import Http404
from django.db.models import Q
from rest_framework import status
from rest_framework.viewsets import GenericViewSet
from rest_framework import mixins
from django.contrib.auth import authenticate, login


class UserSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
    class Meta:
        model = models.UserProfile
        fields = ["username", "password", "email", ]

    def create(self, validated_data):
        user = models.UserProfile.objects.create_user(**validated_data)  # 新增用户必须用create_user,否则密码不是秘文
        return user


# 新建用户
class createUser(mixins.CreateModelMixin, GenericViewSet):
    queryset = models.UserProfile.objects.all()
    serializer_class = UserSerializer


class googleSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
    username = serializers.CharField()
    password = serializers.CharField()

    class Meta:
        model = models.UserProfile
        fields = ["username", "password", ]

    def validate_username(self, username):
        user = authenticate(username=username, password=self.initial_data["password"])
        if not user:
            raise Http404("账号密码不匹配")
        return username


# 绑定Google令牌
class googleBindAPI(APIView):
    def post(self, request):
        queryset = models.Google2Auth.objects.filter(
            Q(user__username=request.data["username"]) | Q(user__email=request.data["username"]))
        if queryset.exists():
            raise Http404("已经绑定令牌,绑定失败")
        serializer = googleSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = models.UserProfile.objects.get(Q(email=request.data["username"]) | Q(username=request.data["username"]))
        login(request, user)
        base_32_secret = base64.b32encode(
            codecs.decode(codecs.encode('{0:020x}'.format(random.getrandbits(80))), 'hex_codec'))
        totp_obj = googletotp.TOTP(base_32_secret.decode("utf-8"))  # 实例化类
        qr_code = re.sub(r'=+$', '', totp_obj.provisioning_uri(request.user.email))
        models.Google2Auth.objects.create(user=user)
        key = str(base_32_secret, encoding="utf-8")
        queryset.update(key=key)
        return Response({"success": True, "msg": "绑定成功", "results": {"qr_code": qr_code}},
                        status=status.HTTP_201_CREATED)


def Google_Verify_Result(secret_key, verifycode):
    t = pyotp.TOTP(secret_key)
    result = t.verify(verifycode)  # 对输入验证码进行校验,正确返回True
    res = result if result is True else False
    print("ret:", res)
    return res

# 用户认证
class loginView(APIView):
    def post(self, request):
        user = authenticate(username=request.data["username"], password=request.data["password"])
        if not user:
            raise Http404("账号密码不匹配")
        try:
            # 判断用户是否已经绑定Google令牌
            key = models.Google2Auth.objects.get(
                Q(user__username=request.data["username"]) | Q(user__email=request.data["username"])).key
        except:
            raise Http404("未绑定令牌")

        if not Google_Verify_Result(key, request.data["code"]):
            # 验证令牌
            return Response({"success": True, "msg": "验证码失效", "results": None}, status=status.HTTP_400_BAD_REQUEST)
        login(request, user)
        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)
        return Response({"success": True, "msg": "登录成功", "results": token}, status=status.HTTP_200_OK)

urls.py路由文件

修改urls.py把url和我们的方法联系起来

app_name = 'myapp1'
from django.conf.urls import include
from django.urls import path
from django_google_auth2.google.bindgoogleauth.bindgoogleauthapi import bind_google_auth_api
from rest_framework import routers
from . import views, gauth

createUserViewRouter = routers.DefaultRouter()                  # 新增用户
createUserViewRouter.register('', gauth.createUser,)

urlpatterns = [
    path('createuser/', include(createUserViewRouter.urls)),    # 新增用户
    path('binggoogleauth/', gauth.googleBindAPI.as_view()),     # 绑定令牌
    path('loginx/', gauth.loginView.as_view()),  #
    path('bing-google-auth-api/', bind_google_auth_api),
    path('testapi/', views.testapi),                            # 测试基础API
    path('testlogin/', views.testlogin.as_view()),              # 测试带参数的api

]

测试

调用新建用户方法

在这里插入图片描述
建立用户返回成功。

绑定用户账号到google auth中

参数为刚刚新建的帐号和密码:
在这里插入图片描述
返回结果:
在这里插入图片描述
绑定成功。

  • 得到一段在google验证APP中识别的代码:
 {
    "success": true,
    "msg": "绑定成功",
    "results": {
        "qr_code": "otpauth://totp/hh@qq.com?secret=VRDIV5XHMVVU637N"
    }
}

把这段代码生成二维码或者手动输入到google验证APP中去,就可以实时生成动态密码了:
在这里插入图片描述

登陆测试

在浏览器输入:http://127.0.0.1:8000/myapp1/loginx/参数为:帐号、密码和动态密码
在这里插入图片描述
结果返回登陆成功,同时返回最新有效的token。
在这里插入图片描述
失败返回出错信息
在这里插入图片描述

PyCharm社区版中使用Django,涉及到安装、配置和项目创建等多个方面。 ### 安装和环境配置 - **安装Django**:在已安装Python环境下,使用命令`pip install Django`来安装Django。同时,要查看自己的PythonDjango版本的兼容性,最好下载Python对应的Django版本,可参考https://blog.youkuaiyun.com/tt75281920/article/details/105181305?utm_source=app [^3][^4]。 - **配置Python解释器**:启动PyCharm后,在`setting`菜单的`Project:backend`子菜单下,配置Python interpreter解释器,需自行安装Python [^3]。 ### 创建Django项目 - **使用PyCharm社区版创建项目**:打开PyCharm社区版,创建一个新项目,在PyCharm下载Django包,打开PyCharm中命令台,使用`django-admin startproject 项目名`创建Django项目,之后创建数据库,最后打开服务器查看项目 [^2]。 - **创建应用**:进入项目目录,使用`python manage.py startapp 应用名`创建应用,例如`cd Demo`后执行`python manage.py startapp web` [^3]。 ### 项目配置 在项目目录下的`settings.py`文件中,`INSTALLED_APPS`段中加入应用名字,示例如下: ```python # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myapp1', ] ``` [^5] ### 启动Django项目 - **终端启动**:在终端中进入项目目录,使用`python manage.py runserver`启动Django Webserver [^1]。 - **PyCharm项目界面启动**:可通过在PyCharm添加配置参数快捷启动Django [^1]。 - **PyCharm社区版直接启动**:这也是运行Django的一种方式 [^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值