如何在Django中使用Ngrok和自签名证书确保本地主机URL的安全

292 阅读6分钟

在Django中使用Ngrok和自签名证书确保本地主机URL的安全

在本地开发应用程序在响应时间和调试过程中是快速可靠的,因为它不需要互联网连接。然而,它也带来了一些挑战。

例如,假设你想建立一个将图片上传到服务器的API,以及一个以你的电脑为服务器在手机上消费你的API的Android应用程序。那么,使用Ngrok来暴露端点是很有效的。

当图片被上传到你的应用程序中的静态文件文件夹时,应用程序会构建一个静态的URL,可以用来自动访问图片。然而,这个URL是以http://localhost/media.imagename.png 的格式出现的,但是Android studio不能使用HTTP 资源。因此,它使用HTTPS 资源。

本教程旨在通过创建一个自签名的证书并使我们的网站成为一个受信任的来源来解决这个问题,这样当Ngrok将我们的端点暴露给公众时,我们的图片看起来就像它们来自于一个受信任的来源。

我们将建立一个Django Posts API,并使用REST框架的可浏览API测试这些场景。

前提条件

读者应该具备以下条件才能跟上。

开始学习

要开始使用,请创建一个虚拟环境并安装Django。Django是一个Python框架,用于构建可扩展的应用程序。

pip install Django 

接下来,在终端执行以下命令,创建一个Django项目。

Django-admin startproject posts-config

上面的命令创建了一个文件夹,主要包含Django应用程序的配置。这就是为什么我把它叫做posts-config

设置REST框架

下一步是启动一个名为blog 的新应用程序。这个应用程序将包含REST框架提供的可浏览API中看到的modelsURLsserializersviews 。然而,首先,执行下面的命令来安装REST框架。

pip install djangorestframework

我们需要将已安装的REST框架添加到settings.py 文件的已安装应用程序列表中。在posts-config 文件夹中,打开settings.py 文件,然后添加以下片段。

INSTALLED_APPS = [

    "rest_framework",
]

模型、序列化器、视图和URL

任何Django REST API应用程序都包括三个主要部分:模型、视图和URL。在本节中,我们将讨论每一个组件。

运行下面的命令,启动一个名为blog的新应用程序。

python manage.py startapp blog

然后,将新创建的应用程序添加到已安装的应用程序列表中。

INSTALLED_APPS = [
    'rest_framework',
    'blog'
]

模型

模型就像数据类,指定数据如何存储在数据库中。例如,它们指定记录中有关数据类型的字段和它在内存中占据的空间。

在博客文件夹中创建的models.py文件中添加以下代码片段。

class Article(models.Model):
    title = models.CharField(max_length=20)
    content = models.CharField(max_length=255)
    date = models.DateTimeField(auto_now=True)
    image = models.ImageField(upload_to="article-images/", null=True)

    def __str__(self):
        return self.title

序列化器

在与models.py 相同的文件夹中创建一个名为serializers.py 的文件。这个文件包含将数据类转换为其他应用程序可以消费的JSON的逻辑。

serializers.py 文件中,添加以下代码片段。

from rest_framework import serializers
from blog.models import Article

class ArticleSerializers(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = "__all__"

视图

在views.py文件中,添加以下代码段,以指定访问URL时要运行的函数。

from rest_framework import viewsets

from .models import Article
from .serializers import ArticleSerializers


class ArticleViewSets(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializers

URLs

URLs指定了访问一个资源的实际路线。例如,我们将有两个URLs;第一个将出现在主应用程序文件夹中,称为blogconfig ,而第二个将出现在blog

blogconfig 文件夹中,添加以下片段。

from django.contrib import admin
from django.URLs import path, include

urlpatterns = [
    path("admin/", admin.site.urls), 
    path("blog", include("blog.urls"))
]

进入应用程序层,创建一个名为urls.py 的新文件,并添加以下代码段。

from django.URLs import path, include
from rest_framework import routers

from .views import ArticleViewSets

router = routers.DefaultRouter()
router.register(r"blog", ArticleViewSets)

urlpatterns = [
    path("", include(router.urls)),
]

设置媒体URL

在这一节中,我们将设置我们的媒体URL,以便应用程序可以重构一个单一文章媒体文件的URL。

在setting.py文件中,添加以下代码段。

MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

接下来,在项目级的urls.py文件中把媒体路径与主URL连接起来,如下所示。

from django.conf.urls.static import static
from django.contrib import admin
from django.URLs import path, include

from blogconfig import settings

urlpatterns = [
    path("admin/", admin.site.urls),
    path("blog", include("blog.urls"))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

接下来,在终端运行以下命令,在数据库中进行迁移并创建表格。

python manage.py makemigrations && python manage.py migrate

现在,如果我们导航到http://127.0.0.1:8000/blogblog/ ,我们可以创建一个帖子,如下图所示。

{
    "id": 1,
    "title": "Blog 1",
    "content": "Content for post 1",
    "date": "2022-04-17T07:00:34.059287Z",
    "image": "http://127.0.0.1:8000/media/article-images/baking.jpeg"
}

然而,帖子的图像URL是不安全的。我们需要确保我们的图像是安全的,以便我们有这样的东西。

{
    "image": "https://127.0.0.1:8000/media/article-images/baking.jpeg"
}

生成一个自签名的证书

要生成一个自签名的SSL证书,在终端运行以下命令。

brew install mkcert

通常情况下,在签发证书时,它们是由一个叫做证书颁发机构的实体签发的。因此,我们需要在我们的机器上安装一个本地证书颁发机构。运行下面的命令来安装一个本地CA。

mkcert -install

现在我们需要为我们的本地应用程序生成证书。在应用程序的根文件夹中,运行以下命令。

mkcert -cert-file cert.pem -key-file key.pem localhost 127.0.0.1

接下来,我们需要设置Django与HTTPS服务器一起运行。执行下面的命令,然后将sslserver ,添加到已安装的应用程序列表中。

pip install django-sslserver

上述配置使我们能够将我们的URL从HTTP 转变为HTTPS ,这样当我们公开图片URL时,它们将显示为使用我们的本地签名证书的安全。

用Ngrok暴露安全端点

Ngrok是一个快速将本地服务器端口暴露给互联网的应用程序。它使应用程序资源可以被整个互联网访问。

要安装Ngrok,运行下面的命令。

brew install ngrok/ngrok/ngrok

接下来,使用下面的命令启动开发服务器。

python manage.py runsslserver

接下来,到Ngrok终端,用命令暴露运行中的服务器。

ngrok http https://localhost:8000

这个命令将在终端上生成一个URL,当粘贴到浏览器上时将是安全的。然而,最好是允许来自所有主机的连接或ngrok生成的特定URL。

Ngrok Generated URL

打开settings.py文件,在ALLOWED_HOSTS部分添加URL或使用* ,允许来自所有主机的连接。

ALLOWED_HOSTS = ['*']

如果我们前往浏览器,图像会被渲染成安全的,如下图所示。如果这个API被移动应用程序使用,Android studio将不会抱怨资源不安全。

Secure endpoint images

总结

我们在本文中使用Django REST框架编写了一个Django REST API。然后,我们在本地测试了我们的API,随后用Ngrok暴露了它。

接下来,我们在本地机器上安装了一个自定义的证书颁发机构,然后生成了一个自签名的证书来保护我们的本地主机端点。最后,我们测试了安全的端点,看看它们是否安全。