如何在Django应用程序中开始使用生物识别2FA的TypingDNA

297 阅读17分钟

使用TypingDNA在Django应用程序中开始使用生物识别2FA

你是否曾经想在你的Django网络应用中实现生物识别双因素认证?如果你的回答是肯定的,那么这篇文章正是你需要开始的。

本文将展示一个将TypingDNA服务集成到Django网络视频播放器应用程序的分步指南。

在Django应用程序中使用TypingDNA的生物识别2FA

TypingDNA是一个双因素认证API,它可以轻松地整合生物识别认证,利用强大的打字分析来保护你网站上的用户账户。

TypingDNA通常可以帮助你学习用户的打字模式,与之匹配,然后在登录后使用它来验证用户。这种双重用户验证就是所谓的 "双因素认证"。

使用TypingDNA进行注册

为了开始使用,我们需要在他们的网站TypingDNA上创建一个账户。

在我们完成了账户的创建和设置后,我们应该看到一个类似下图的页面。

Signup-page

复制你的api_keysecret_key ,并把它们存放在安全和容易检索的地方。

建立我们的Django应用程序

先决条件

  • 在你的电脑上安装了[Python]3.7及以后的版本。
  • 在你的电脑上安装了[Django]。

克隆项目

为了建立我们的Django应用程序,我们需要开发视频播放器应用程序的前端和后端。我们已经为我们预制了视频应用程序,并将主要集中在将生物识别技术与TypingDNA整合在一起。

你可以克隆GitHub仓库,并通过执行下面的命令来运行该应用程序。

git clone https://github.com/Nomzy-kush/mine.git
cd typingdnavideoplayer

以下是项目结构。

project-structure

我们需要安装我们项目所需的requests 模块,以便与TypingDNA的API进行交互。

执行下面的命令,将Django和request安装到我们的项目中。

pip install requests
pip install django

运行应用程序以确保所有的配置都正常。执行下面的命令来启动开发服务器。

python manage.py runserver

application-running

在浏览器上导航到localhost,测试我们的应用程序是否正在运行。

sign-in-page

安装TypingDNA库

要安装TypingDNA,我们需要下载实现双因素认证所需的JavaScript文件。

你可以从GitHub,或TypingDNATypingDNA API下载该文件。

下载完JavaScript文件后,打开App 文件夹,将typingdna.js 文件放到静态文件夹中。我们还需要下载并导入TypingDNAAutocomplete DisablerTyping Visualizer 文件。

这些文件将使用户在输入所需文本时看到他们的打字模式被记录下来。从TypingDNArepo中下载autocomplete-disabler.jstyping-visualizer.js ,并将它们存放在我们的Django应用程序的static 文件夹中。

最终的项目结构应该如下图所示。

project-structure

在下载并将文件放在适当的目录中后,我们需要修改Video 表的模型,以显示由特定用户添加的视频。

要做到这一点,用下面的代码片断更新models.py 文件。

from django.db import models
from django.shortcuts import reverse
from django.contrib.auth.models import User
# Create your models here.
class Video(models.Model):
    title= models.TextField()
    summary= models.TextField()
    image= models.ImageField()
    file = models.FileField(blank=True,null=True)
    link = models.CharField(max_length=200,blank=True,null=True)
    user=models.ForeignKey(User, null=True,blank=True, on_delete=models.CASCADE)
    slug = models.SlugField()
    paginate_by = 2
    def __str__(self):
        return self.title
    def get_absolute_url(self):
        return reverse("App:details", kwargs={
            'slug': self.slug
        })

接下来,我们需要创建一个UserProfile 表来验证捕获的打字模式,其中包含TypingDNA认证用户在我们数据库中的额外细节。

用下面的代码更新models.py 文件。

from django.db import models
from django.shortcuts import reverse
from django.contrib.auth.models import User
### Create your models here.
class Video(models.Model):
    title= models.TextField()
    summary= models.TextField()
    image= models.ImageField()
    file = models.FileField(blank=True,null=True)
    link = models.CharField(max_length=200,blank=True,null=True)
    user=models.ForeignKey(User, null=True,blank=True, on_delete=models.CASCADE)
    slug = models.SlugField()
    paginate_by = 2
    def __str__(self):
        return self.title
    def get_absolute_url(self):
        return reverse("App:details", kwargs={
            'slug': self.slug
        })
class UserProfile(models.Model):
    user = models.OneToOneField(User, related_name="profile", on_delete=models.CASCADE)
    private_key = models.TextField()

在用上面的代码更新models.py 文件后,我们需要为数据库运行迁移程序。执行下面的命令来进行数据库迁移。

python manage.py makemigrations
python manage.py migrate

如果我们的迁移运行成功,我们应该看到下面的结果。

migrations

让我们用下面的代码片段编辑views.py 文件中的videos 视图,以便在前端只呈现一个特定用户的视频。

def videos(request):
    paginator= Paginator(Video.objects.filter(user=request.user),2)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    context={"page_obj":page_obj}
    return render(request,"videos.html",context)

我们需要更新register 视图,为每个注册用户创建新的UserProfile 对象。要做到这一点,编辑register 视图,在有user.save 的一行之后输入下面的代码片段。

userprofile=UserProfile.objects.create(user=user)
userprofile.save()

TypingDNA检查用户端点

check-user-endpoint

TypingDNA API检查用户端点帮助我们检查一个用户是否存在,然后检查他们所保存的打字模式的数量。如果用户已经保存了打字模式,那么就可以进行验证。我们建议你至少保存两个打字模式,以便进行有效的验证。

对于我们的views.py 文件中的login 视图,我们需要在会话中创建一个变量来检查TypingDNA是否验证了当前用户会话。

用下面的代码片断更新你的login 视图。

def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        user = auth.authenticate(username=username, password=password)
        if user is not None:
            auth.login(request, user)
            if 'user' in request.session:
                return redirect("App:videos")
            else:
                return redirect("App:verify")
        else:
            context={"message":"Invalid login credentials"}
            return render(request,"login.html",context)
    else:
        return render(request,"login.html")

注册用户的打字模式

注册页面

注册页面允许用户向TypingDNA注册他们的打字模式,以便将来进行验证。我们将建立实现这一功能所需的HTML页面。

正如我们在克隆的项目中看到的,我们已经有了enroll.html 文件。用下面的代码片断更新模板文件夹中的enroll.html 文件。


{% load static %}


<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">

<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>


<style>
 body {
background-color: #b2beb5
}
</style>

<div class="container">

        <div class="row justify-content-center align-items-center" style="height:100vh">

            <div class="col-4">

                <div class="card">

                  <center><h2>Setup TypingDNA 2FA on your Video Player</h2></center>

                  <br>

                    <div class="card-body">

                {% if messages %}

                  {% for message in messages %}

                        <div class="alert alert-danger" role="alert">

                        {{message}}

                        </div>

                    {% endfor %}

                  {% endif %}



                      <div id="failed-auth" class="alert alert-danger" role="alert" style="display: none">

                          <strong>You have not completed your authentication, please type the text above</strong>

                      </div>


                        <form method="POST">

                          {% csrf_token %}

                            <div class="form-group">

                              <p class="mb-0" style="color:red;"><strong>"I am authenticated by the way I type"</strong></p>

                              <br>

                                <input type="text" class="form-control disable-autocomplete" id="auth-text" name="type" placeholder="enter text seen above">

                            </div>

                            <input type="hidden" id="tp" name="tp">

                            <button class="btn btn-primary" type="button" class="btn btn-success" onclick="startAuthentication()">Start Authentication</button>

                        </form>

                    </div>

                </div>

            </div>

        </div>

    </div>

<script src="{% static 'typingdna.js' %}">
    </script>

    <script src="{% static 'autocomplete-disabler.js' %}">
    </script>

    <script src="{% static 'typing-visualizer.js' %}">
    </script>

在上面的HTML代码中,你会注意到在我们文件的末尾,我们导入了之前下载的typingdna.js,autocomplete-disabler.js, 和typing-visualizer.js 文件。通过jinja标签,我们在前台渲染了从后端传来的信息。

TypingDNA的visualizer只捕捉带有disable-autocomplete 类属性的输入元素,这就是为什么我们在上面的input HTML标签中加入了它。

向TypingDNA提交打字模式

在创建了上面的招生页面后,我们需要将收集到的打字模式发送到TypingDNA进行记录。要做到这一点,我们需要将TypingDNA记录器和可视化器集成到注册页面中,以注册我们的用户。

创建一个TypingDNA和Autocomplete-disabler类的实例,这样你就可以在用户开始打字时记录他/她的打字模式。

enroll.html 页面中我们导入TypingDNA的那一行之后,添加下面的代码片段。


<script>
  var typingdna = new TypingDNA();
      var auto_complete_disabler = new AutocompleteDisabler({
        showTypingVisualizer: true,
        showTDNALogo: true
      });
</script>

autocomplete-disabler

接下来,创建一个变量来存储我们的用户所捕捉到的打字模式,并创建一个名为beginAuthentication 的函数,当用户输入授权文本时触发。


  <script>
  var typingdna = new TypingDNA();
  var auto_complete_disabler = new AutocompleteDisabler({
    showTypingVisualizer: true,
    showTDNALogo: true
  });
  var typing_patterns = [];
  function beginAuthentication() {
    document.getElementById("failed-auth").style.display = "none";
    document.getElementById("auth-text").value = "";
    TypingDNA.stop();
    let typing_pattern = tdna.getTypingPattern({
      type: 1,
      text: "I am authenticated by the way I type"
    });
    if (typing_pattern == null) {
      document.getElementById("failed-auth").style.display = "block";
    } else {
      typing_patterns.push(typing_pattern);
      if (typing_patterns.length == 3) {
        let tp = typing_patterns[0] + ";" + typing_patterns[1] + ";" + typing_patterns[2];
        document.getElementById("tp").value = tp;
        document.forms[0].submit();
      } else {
        alert("Successfully logged typing pattern, please type the text again to improve accuracy");
      }
    }
    TypingDNA.reset();
    TypingDNA.start();
  }
</script>

在上面的代码中,我们调用beginAuthentication 函数来停止记录用户的击键,这样我们就可以记录和分析当前的打字模式。

然后,我们使用TypingDNA提供的sametext 捕获方法捕获了用户的打字模式记录。你可以在他们的官方文档中探索其他TypingDNA的方法,这里api.typingdna.com/#api-captur…

在捕捉到用户的打字模式后,我们继续验证打字模式是否被成功捕捉。如果捕获成功,我们将打字模式存储在我们先前创建的typing_patterns 变量中。然而,如果捕获不成功,我们就会显示TypingDNA反映的错误信息。

根据TypingDNA的文档,为了确保准确的认证,我们的用户捕获的打字模式,用户必须注册他/她的打字模式至少三(3)次。为了达到这个目的,我们在提交表格之前检查用户是否注册了所有三次。

如果用户没有满足三次注册,我们只是存储当前的模式,并使用TypingDNATypingDNA.reset() 方法重新启动注册。

我们也会重启TypingDNA.start() 方法,再次启动记录器,同时跟踪用户完成的注册次数。TypingDNA要求所有发送的打字模式应该串联成一(1)个字符串,用分号隔开。

enrollment-page

保存记录的打字模式

TypingDNA需要对记录的打字模式进行分析,并将其用于验证用户。为了做到这一点,我们需要将记录的打字模式保存到我们的数据库。然后,我们利用TypingDNA的"自动 "端点,帮助TypingDNA API提交和保存捕获的打字模式。

TypingDNA的自动端点

现在让我们来谈谈"自动 "端点是如何工作的。自动 "端点使用用户的ID为当前用户捕获的前三个模式中的每一个注册。

在注册了前三种模式后,你可以使用其他每一种模式进行认证。

建立我们的辅助库

为了让我们的Django应用程序与TypingDNA API交互,我们需要创建一个辅助库来简化我们的工作。在你的App 文件夹中创建一个名为typingdnahelper.py 的新文件,并将下面的代码片段加入其中。

import base64
import hashlib
import requests
class TypingDNA:
    def __init__(self, apiKey, apiSecret):
        self.apiKey = apiKey
        self.apiSecret = apiSecret
        self.base_url = "https://api.typingdna.com"
        authstring = f"{apiKey}:{apiSecret}"
        self.headers = {
            "Authorization": "Basic " + base64.encodebytes(authstring.encode()).decode().replace("\n", ""),
            "Content-Type": "application/x-www-form-urlencoded"
        }
    def auto(self, id, tp, custom_field=None):
        url = f"{self.base_url}/auto/{id}"
        data = {
            "tp": tp,
            "custom_field": custom_field
        }
        return requests.post(url, headers=self.headers, data=data)
    def check_user(self, id, user_type=None, text_id=None, custom_field=None):
        url = f"{self.base_url}/user/{id}"
        params = {
            "type": user_type,
            "text_id": text_id,
            "custom_field": custom_field
        }
        return requests.get(url, headers=self.headers, params=params)
    def hash_text(self, text):
        return hashlib.sha1((text + text[::-1]).encode()).hexdigest()

TypingDNA需要一个用户ID来保存用户的打字模式,所以我们创建了一个hash_text 方法,在发送前对用户的ID进行散列。

保存用户的打字模式

在建立了我们的辅助库之后,我们可以开始在我们的账户中保存用户的打字模式,以便将来进行匹配。让我们首先将辅助库类导入我们的Django应用程序,并通过提供我们先前从TypingDNA仪表盘上保存的apiKeyapiSecret ,来创建我们的辅助类实例。

from . typingdnahelper import TypingDNA
tdna = TypingDNA("apiKey", "apiSecret")

下面的图片显示了views.py 的导入。

import

用下面的代码片断更新enroll 视图,以保存仪表盘中收到的模式。

def enroll(request):
    if request.method=="POST":
        tp = request.POST.get("tp")
        username = request.session["reg_user"]["username"]
        r = tdna.auto(tdna.hash_text(username), tp)
        if r.status_code == 200:
            user=UserProfile.objects.get(user=User.objects.get(username=username))
            user.typingdna_secured=True
            user.save()
            request.session["typingdna_auth"] = True
            messages.add_message(request, messages.INFO,"You have successfully registered TypingDNA 2FA", "success")
            return redirect("App:videos")
        else:
            messages.add_message(request, messages.INFO,r.json()["message"], "danger")
            return redirect("App:enroll")
    return render(request,"enroll.html")

在上面的代码中,我们收集了用户的打字模式并将其存储在tp 变量中。然后,我们请求TypingDNA API的auto 端点,以验证所提供的打字模式是否与该用户注册的打字模式相符。

然后我们检查请求的状态代码是否成功(状态代码200)。如果是这样的话,我们会更新数据库中的用户数据,以表明他们已经被注册。

然后我们将把当前登录的会话标记为已通过session["typingdna_auth"] = True ,然后将用户重定向到他们的仪表板。然而,如果认证不成功(由于TypingDNA的错误),我们将向用户提示错误信息,并让他们重新尝试注册过程。

在成功注册TypingDNA后,我们会被重定向到一个类似于下面图片的页面。

dashboard

使用TypingDNA认证新用户

建立我们的登录逻辑

在注册并在TypingDNA上注册了我们的打字模式后,我们现在可以登录并实现我们的双因素认证。

login

在上面的图片中,我们的login 视图检查用户是否被设置在会话中。如果用户被设置,那么用户将被重定向到查看所有视频的页面。如果用户没有被设置,那么用户将被重定向到用他们的输入模式来验证他/她的2FA。

建立验证页面

现在我们要建立一个验证页面,在那里我们将使用TypingDNA生物识别技术来验证用户的身份。

让我们用下面的代码片断更新我们的verify.html 文件。


{% load static %}

<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">

<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>


<style>
 body {
background-color: #b2beb5
}
</style>

<div class="container">

        <div class="row justify-content-center align-items-center" style="height:100vh">

            <div class="col-4">

                <div class="card">

                  <center><h2>2FA Verify Your Typing Style</h2></center>

                 {% if messages %}

                  {% for message in messages %}

                        <div class="alert alert-danger" role="alert">

                        {{message}}

                        </div>

                    {% endfor %}

                  {% endif %}


                  <div id="failed-auth" class="alert alert-danger" role="alert" style="display: none">

                      <strong>You have not completed your authentication, please type the text above</strong>

                  </div>          

                    <div class="card-body">

                        <form method="POST">

                          {% csrf_token %}

                            <div class="form-group">

                              <p class="mb-0" style="color:red;"><strong>"I am authenticated by the way I type"</strong></p>

                              <br>

                                <input type="text" class="form-control disable-autocomplete" id="auth-text" name="type" placeholder="enter text seen above">

                            </div>

                            <input type="hidden" id="tp" name="tp">

                          <button class="btn btn-primary" type="button" class="btn btn-success" onclick="startAuthentication()">Start Authentication</button>

                        </form>

                        <p class="mb-0" style="color:blue;"><strong>Can't verify?<a href="verify-email"> Try verifying with your email</a></strong></p>

                    </div>

                </div>

            </div>

        </div>

    </div>

    <script src="{% static 'typingdna.js' %}">
    </script>

    <script src="{% static 'autocomplete-disabler.js' %}">
    </script>

    <script src="{% static 'typing-visualizer.js' %}">
    </script>

verify-page

在这个页面中,用户将通过他们预先注册的打字模式进行验证。

使用TypingDNA进行验证

在准备好我们的verify.html 页面后,我们需要使用TypingDNA记录器开始验证打字模式,这将帮助我们记录打字模式并进行匹配。

首先,我们将创建两个变量,typingdnaauto_complete_dIsabler ,它们是TypingDNA和AutocompleteDisabler类的实例。这将确保一旦用户开始打字,他/她就开始被记录(作为击键事件的历史)。

我们还调用了beginAuthentication ,该函数使用TypingDNA.stop() 方法停止记录用户的击键,并对其进行分析。

enroll.html 页面中的TypingDNA导入后,马上添加下面的代码。


<script>
  var typingdna = new TypingDNA();
      var auto_complete_disabler = new AutocompleteDisabler({
        showTypingVisualizer: true,
        showTDNALogo: true
      });
      function beginAuthentication() {
        document.getElementById("failed-auth").style.display = "none";
        document.getElementById("auth-text").value = "";
        TypingDNA.stop();
        let typing_pattern = typingdna.getTypingPattern({
          type: 1,
          text: "I am authenticated by the way I type"
        });
        if (typing_pattern == null) {
          document.getElementById("failed-auth").style.display = "block";
          TypingDNA.reset();
          TypingDNA.start();
        } else {
          document.getElementById("tp").value = typing_pattern;
          document.forms[0].submit();
        }
      }
</script>

当用户的打字模式被捕获后,我们检查捕获是否成功。如果不成功,我们会显示一个错误信息,否则我们会提交表单,如果成功的话,我们会发送记录的打字模式进行验证。

更新我们的verify 视图,用TypingDNA API中的auto 端点捕捉并验证提交的用户打字模式。

def verify(request):
    if request.method == "POST":
        tp = request.POST.get("tp")
        username = request.user.username
        r = tdna.auto(tdna.hash_text(username), tp)
        if r.status_code == 200:
            if r.json()["result"] == 1:
                request.session["typingdna_auth"] = True
                return redirect("App:videos")
            else:
                messages.add_message(request, messages.INFO,"You failed the TypingDNA verification check, please try again", "danger")
                return redirect("App:verify")
        else:
            messages.add_message(request, messages.INFO,r.json()["message"], "danger")
            return redirect("App:verify")
    return render(request,"verify.html")

在上面的Python代码中,我们检查了从前端发送的请求是否是一个POST请求。如果是这样,我们就继续捕捉POST请求,tp ,这是记录的打字模式,并将username 设置为当前用户。我们使用用户名作为用户ID,这就自动完成了所需的认证。

然后我们向TypingDNAauto 方法发出请求,同时发送当前用户的用户ID和收集的打字模式tp 。然后,如果验证成功,auto 方法返回一个status code 200 ,如果验证不成功,则返回一个错误信息。

如果验证成功,我们将会话中的typingdna_auth 设置为真,并将用户重定向到videos 页面。然而,如果验证不成功,我们在verify 页面上显示来自auto 端点的错误信息。

回归验证选项

假设用户不能使用TypingDNA的验证页面,我们需要为用户提供一个后备选项,以确保登录安全。早些时候,在注册TypingDNA的时候,你可能已经注意到了第三个选项,如果生物特征打字验证失败,可以用OTP完成双因素认证。

在这种情况下,我们将使用发送到用户邮箱的必要的魔法链接,当用户点击时,它会自动进行认证。

在模板文件夹中创建一个名为verify-email.html 的新文件,并添加以下HTML代码片段。


{% load static %}

<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">

<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>


<style>
 body {
background-color: #b2beb5
}
</style>

<div class="container">

        <div class="row justify-content-center align-items-center" style="height:100vh">

            <div class="col-4">

                <div class="card">

                  <center><h2>Verify With Your Email</h2></center>

                  {% if messages %}

                        <div class="alert alert-danger" role="alert">

                        {{messages}}

                        </div>

                  {% endif %}

                  {% if error %}

                  <div id="failed-auth" class="alert alert-danger" role="alert" style="display: none">

                      <strong>Cannot verify with email!!</strong>

                  </div>

                    {% endif %}

                      {% if messages %}

                      {% else %}

                    <div class="card-body">

                        <form method="POST">

                          {% csrf_token %}

                            <div class="form-group">

                              <center><p class="mb-0" style="color:green;"><strong>"Get a link in your Email"</strong></p></center>

                              <br>

                                <input type="hidden" name="verify_email" value="true" />

                            </div>

                          <center><button class="btn btn-primary"  type="submit" >Send Link</button></center>

                        </form>

                    </div>

                    {% endif %}

                </div>

            </div>

        </div>

    </div>

email-verification

创建令牌文件

我们需要创建一个tokens.py 文件,我们将用它来生成用于验证的神奇链接。创建一个tokens.py 文件并添加以下python代码段。

from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.utils import six
class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
    def _make_hash_value(self, user, timestamp):
        return (
            six.text_type(user.pk) + six.text_type(timestamp)
        )
account_activation_token = AccountActivationTokenGenerator()

创建激活令牌页面

我们需要创建一个activation.html 文件,我们将用它来显示发送给用户的链接。在模板目录下创建一个activation.html 文件并添加以下HTML代码。


{% autoescape off %}

Hi {{ user.username }},


Please click on the link below to verify your login:


http://{{ domain }}{% url 'App:activate' uidb64=uid token=token %}

{% endautoescape %}

建立登录激活逻辑

现在,我们将建立我们的逻辑,即如何生成和发送激活令牌。

首先,我们需要导入所需的模块和库。

复制并粘贴下面的代码到你的views.py 文件。

from django.views.generic import  View
from . tokens import account_activation_token
from django.contrib.sites.shortcuts import get_current_site
from django.template.loader import render_to_string

我们需要在用户每次在verify-email 页面上请求激活令牌时创建激活令牌。通常情况下,我们会将激活链接发送到用户的电子邮件,但在这种情况下,我们只需在控制台显示该链接。

然而,如果你想把激活链接发送到用户的邮箱,你将需要使用Django的SMTP模块。

用下面的代码更新你在views.py 文件中的verify_email 函数。

def verify_email(request):
    if request.method=="POST":
        name=request.POST.get("verify_email")
        if name=="true":
            context={"messages":"A link has been sent to your email"}
            current_site = get_current_site(request)
            message = render_to_string('activation.html', {
                'user': request.user,
                'domain': current_site.domain,
                'uid': request.user.pk,
                'token': account_activation_token.make_token(request.user),
                })
            print(message)
            return render(request,"verify-email.html",context)
        else:
            context={"error":"true"}
            return render(request,"verify-email",context)
    return render(request,"verify-email.html")

在上面的代码片段中,我们检查了从前端收到的请求是否是一个POST请求。如果是这样,我们继续收集POST请求中的数据,为name ,然后检查该值是否为 "true"。

如果是这种情况,我们使用render_to_string 函数创建一个消息,将激活令牌和其他所需的数据发送到activation_email 页面,让用户看到。

我们使用从我们的tokens.py 文件中导入的make_token 方法来创建令牌,该方法将使用用户的用户名来制作令牌。

激活链接在下面的图片中被发送给用户,并显示在控制台供用户查看。

link-sent

verification-token

确认页面

在templates文件夹中创建一个新的文件名confirm.html ,并用代码片段更新该文件,如下所示。


{% load static %}


<center>{% if message %}

  <h2>{{message}}</h2>

{% endif %}

</center>

验证激活令牌

为用户创建的激活令牌必须在用户点击后进行验证。要做到这一点,更新你的views.py 文件,在文件的开头放置以下Python代码。

class ActivateAccount(View):
    def get(self, request, uidb64, token, *args, **kwargs):
        try:
            uid = uidb64
            user = User.objects.get(pk=uid)
        except (TypeError, ValueError, OverflowError, User.DoesNotExist):
            user = None
        if user is not None and account_activation_token.check_token(user, token):
            request.session["verify_email"]= True
            auth.login(request,user)
            return redirect('App:videos')
        else:
            context={"message":'The confirmation link was invalid, possibly because it has already been used.'}
            return render(request,'confirm.html',context)

在上面的代码片段中,我们创建了get 方法,它接收点击的激活令牌,并从中收集验证所需的数据。然后,我们做了一个try...except 缓存,检查在与数据库中的用户相匹配的uid ,是否有错误。

如果没有错误,用户会自动登录,会话中的 "verify_email "被设置为True。然而,如果在将uid 与数据库中的用户进行匹配时出现任何问题,用户将被设置为 "无",并且产生的错误信息将被发送到confirm.html 页面中呈现。

最后,我们需要创建一个新的URL来处理激活令牌的验证。在urls.py 文件中添加以下代码到我们的urlpatterns ,通过ActivateAccount 类来验证激活令牌。

path('activate/<uidb64>/<token>/', views.ActivateAccount.as_view(), name='activate')

下面的图片显示了导航到一个错误的、已使用的或超时的激活令牌的结果。

invalid-token

添加视频到数据库

为了将视频添加到我们可以播放的数据库中,我们需要访问管理页面并登录。让我们在admin上导航到管理页面并登录。

登录成功后,点击Videos 旁边的+ 按钮,添加一个新的视频,并提供所需的细节,如下图所示。

add-video

在提供了我们的视频所需的细节后,我们将点击保存视频并返回到主页。转到视频页面。你会发现我们现在有一个新的视频,我们可以播放。

added-video

结论

在将TypingDNA与Django整合的过程中,我们几乎不费吹灰之力就实现了在Python网络应用中使用生物识别技术的双因素认证。我们还看到通过使用TypingDNA分析用户的打字模式来创建和验证身份是多么容易。