用Twilio认证和保护用户身份 Flask管理数据库

338 阅读20分钟

在建立一个面向公众的网站时,有许多因素需要考虑。例如,一个开发者需要考虑什么是必要的,不仅要保护用户,还要保护项目。他们需要弄清楚如何安全地存储数据--尤其是当项目由敏感信息组成时。

在本教程中,你将学习如何开发一个功能网站,在允许用户向你的云存储上传图像文件之前,对用户进行认证并保护他们的身份。在对用户进行认证后,该项目可以让用户选择通过网站上传图像文件,并将文件存储在云端。

该应用程序将使用两个关键技术。

  • Twilio Verify生成一次性密码传递到用户的手机上,这样他们就可以验证自己的身份并访问你的应用程序。为了更加安全,考虑实施双因素认证。
  • 亚马逊简单存储服务(Amazon S3)来存储文件。亚马逊S3为任何需要扩展的项目提供快速和廉价的存储解决方案。Python代码将与S3桶互动,以灵活的权限变化设置来存储和检索对象。

教程要求

  • Python 3.6或更新版本。如果你的操作系统没有提供Python解释器,你可以去python.org下载一个安装程序。
  • 一个免费或付费的Twilio账户。如果你是Twilio的新用户,现在就可以得到你的免费账户!(如果你通过这个链接注册,Twilio会在你升级时给你10美元的积分。)
  • 创建一个免费账户或登录到你的AWS控制台
  • 一张与你的AWS账户相连的信用卡,以防你超过了免费级别的资格选项。值得注意的是,如果你在AWS上部署一个应用程序,你应该采取额外的预防措施。确保你保持在免费层级的限制之内,以避免在月底有多余的费用。请参考S3定价指南和适当的文档,以防止未来收费。

设置环境

在你的终端中创建一个名为_verify-aws-s3_的项目目录,以便进行跟踪。如果你使用的是macOS或Linux,在终端输入这些命令。

$ mkdir verify-aws-s3
$ cd verify-aws-s3

由于我们将为这个项目安装一些Python软件包,我们需要创建一个虚拟环境

如果你使用的是Linux或macOS系统,打开终端并输入以下命令。

$ python -m venv venv
$ source venv/bin/activate
(venv) $ pip install flask boto3 awscli twilio python-dotenv 

注意。取决于 你所使用的Python版本_,你可能需要指定python3 。_

如果你在Windows机器上,在一个提示窗口中输入以下命令。

$ python -m venv venv
$ venv\Scripts\activate
(venv) $ pip install flask boto3 awscli twilio python-dotenv 

如果你想了解更多关于这些包的信息,你可以在这里查看。

  • Flask框架,用来创建从Twilio接收消息通知的Web应用程序。
  • python-twilio包,用于通过Twilio服务发送消息。
  • python-dotenv包,用于读取配置文件。
  • AWS的Python SDK,即Boto3,用于创建对AWS服务(如S3)的高级访问。
  • awscli包可以从命令行访问亚马逊网络服务。

创建你的第一个Twilio Verify

要使用Twilio Verify,必须生成一个服务。进入Twilio Verify仪表板,你应该在一个名为 "服务"的页面上。点击红色的加号**(+**)按钮,创建一个新的服务。给这个服务起一个友好的名字 "site-verify"。这个友好的名字将显示在发送到用户手机的短信上,所以如果你有另一个你想使用的名字,如"<你的名字>网站验证",请随时这样做。

在你输入了友好的名称后,点击红色的创建按钮进行确认。

Create new Twilio Verify service with friendly name site-verify

创建Twilio Verify服务将引导你进入_常规设置_页面,你可以看到与你的新Twilio Verify服务相关的属性。

Twilio Verify general settings page with service SID

打开你喜欢的代码编辑器,在项目的根目录下创建一个_.env_文件。在这个文件中,创建一个名为VERIFY_SERVICE_SID 的新环境变量,并复制和粘贴网页上的SERVICE SID作为这个新变量的值。

为了完成_.env_文件,创建两个额外的环境变量:TWILIO_ACCOUNT_SIDTWILIO_AUTH_TOKEN 。你可以在Twilio控制台找到这些变量的值,如下图所示。

Twilio Console AUTH TOKEN and SID credentials

设置一个开发用的Flask服务器

由于我们将在整个项目中利用Flask,我们需要设置开发服务器。在你的项目中添加一个_.flaskenv_文件(确保你有前面的点),其中包括以下几行。

FLASK_APP=app.py
FLASK_ENV=development

这两行非常有用,在测试和调试你的项目时可以节省时间。FLASK_APP 告诉Flask框架我们的应用程序的位置,FLASK_ENV 将Flask配置为在调试模式下运行。

这些行很方便,因为每次你保存源文件时,服务器都会重新加载并反映这些变化。

创建了.flaskenv后,在终端运行flask run ,启动Flask框架。你应该看到与下面的截图类似的输出。

terminal showing the output of "flask run" command. flask is running with environment on development

该服务现在正在监听5000端口的传入连接。

注意,调试模式是激活的。在这种模式下,Flask服务器会自动重启,以纳入你对源代码的任何进一步修改。然而,由于你还没有_app.py_文件,所以什么也不会发生。不过,这也是一个很好的指标,说明一切都安装正确了。

当你探索代码的时候,请随意让Flask在后台运行。我们将在最后对整个项目进行测试。

导航到Amazon S3仪表板

在浏览器中登录到AWS控制台,点击网页左上角的_服务_下拉菜单。点击_存储_标签下的 "S3 "或在搜索栏中输入名称,以访问S3仪表板。

AWS Services dashboard displaying the S3 option under the Storage section

创建一个S3桶

点击橙色的 "创建桶"按钮,如下图所示,将被转到_常规配置_ 页面。

Amazon S3 dashboard with option to Create bucket

给水桶一个独特的名字,不要包含空格或大写字母。

请记住,桶的名称必须是创造性的和独特的,因为亚马逊要求在一组区域内有独特的桶的名称。由于本文使用的是 "lats-image-data "这个名字,它不再适用于其他客户。

同样重要的是要知道,必须明智地设置AWS区域以节省成本。区域是由AWS数据中心的位置决定的,因此,通常建议选择离你最近的一个。

例如,一个美国开发者需要确保他们的实例在美国境内。住在加利福尼亚的人可能会选择 "US West (N. California) (us-west-1)",而另一个住在俄勒冈州的开发者则倾向于选择 "US West (Oregeon) (us-west-2)"。

本教程中的桶将被命名为 "lats-image-data",并设置为 "US East (Ohio) us-east-2 "区域,但请根据你的使用情况进行相应的修改。

请随意将后面的所有设置保留为默认值。然后,向下滚动并点击橙色的创建桶按钮,在S3控制台看到新创建的桶,你可以在下面的图片中看到。

注意。保留一份该桶的AWS区域值(小写的连字符),因为我们以后会需要它。

Amazon S3 dashboard showing list of buckets

在亚马逊网络服务上创建一个IAM用户

为了使Flask应用程序能够工作,需要创建一个身份和管理(IAM)用户。点击网页左上方的_服务_下拉菜单。向下滚动点击_安全、身份和合规标签_下的 "IAM",或在搜索栏中输入名称,以访问IAM管理控制台。

AWS dashboard with Services tab opened to see the Security, Identity, and Compliance section with IAM underneath

在控制台左侧的仪表板下选择_用户_,点击添加用户按钮,如下图所示。

Instructions to Add user under the Identity and Access Management (IAM) console

输入一个用户名,如 "myfirstIAMuser",并勾选给予该用户_程序性访问权_。这就足够了,因为它提供了使用AWS SDK和API所需的访问密钥ID和秘密访问密钥

Options to Set user details in the user creation page for IAM users with the user name "myfirstIAMuser"

点击页面底部标有 "下一步"的蓝色按钮**。权限**。选择 "直接附加现有策略 "的方框,并通过 "AmazonS3FullAccess "过滤策略。当它出现时,选中政策名称旁边的复选框。

Settings page to Set permissions for the newly created IAM user with policy name AmazonS3FullAccess

通过点击 "下一步"向前推进**。标签**"按钮。标签用于为不同的使用情况对AWS资源进行分类,使其更方便地跟踪它们。例如,当你正在进行大规模的项目,需要以首选结构组织AWS计费成本时,这将有所帮助。鉴于这个项目相对较小,没有必要为这个IAM用户添加标签--特别是如果你只打算在这个特定的应用中使用AWS。

继续并点击下一步。审查。查看为 "myfirstIAMuser "设置的细节,最后点击创建用户按钮。点击下载****.csv下载名为_new_user_credentials.csv_的CSV文件,其中包含访问密钥ID和秘密访问密钥的变量。

配置AWS IAM用户凭证

在终端,键入aws configure ,并在提示下输入_new_user_credentials.csv_文件中的 "访问密钥ID"。按回车键,并从文件中输入 "AWS秘密访问密钥 "的 "秘密访问密钥"。再次按回车键。

对于 "默认区域名称",输入你之前复制的S3 Bucket的小写连字符的区域。在本文中,该区域是 "us-east-2"。按回车键确认,再按一次 "默认输出格式"。

现在凭证配置正确了,你的项目将能够创建到S3桶的连接。

创建一个合格用户的数据库文件

在本教程中,我们将硬编码一个允许进入网站的账户列表,以及他们的电话号码。然而,在生产环境中,你可能会使用一个数据库,如PostgreSQL。

我们将完全跳过密码,只是为了这个项目教程的范围。然而,在生产环境中,处理密码是必不可少的。请记住,如果你要使用你的数据库,你将不得不避免将密码作为明文存储。

注意。有很多库可以帮助开发者在Flask应用程序中管理密码,如 Flask Security__.

在项目的根目录下创建一个名为_settings.py_的文件,并将下面的代码复制到该文件中。

KNOWN_PARTICIPANTS = {
  'twilioisthebest@twilio.com': "<YOUR_PHONE_NUMBER>",
  'cedric@twilioquestgame.com': '+15552211986',
  'twilioquestthebest@twilio.com': '+15553242003',
}

这个字典可以根据你的需要修改,以包括不同的电子邮件和电话号码。确保电话号码是E.164格式的,如上面_settings.py_的例子所示。

请确保将你的电话号码添加到字典中的一个现有项目中,或者用你的信息创建一个新项目。每个电子邮件地址都是一个唯一的键。这在我们的案例中很有帮助,因为我们想在登录步骤中快速查找用户。

规划项目的逻辑

项目的逻辑流程如下。

  1. 一个来自KNOWN_PARTICIPANTS 的用户在网站的主页上输入了他们的电子邮件地址。
  2. Flask应用程序向用户的手机号码发送一个一次性密码。
  3. 用户被提示输入他们从手机上收到的密码以验证他们的身份。
  4. 如果用户正确输入密码,他们会被转到一个页面,上传他们选择的_.jpg_、.png 或_.jpeg_图片。
  5. 该媒体文件将被上传到本教程早期创建的Amazon S3桶。

说到这里,让我们开始编码吧!

在你的工作目录中,创建一个名为_app.py_的文件并复制和粘贴以下代码。

import os
from dotenv import load_dotenv
from twilio.rest import Client
from flask import Flask, request, render_template, redirect, session, url_for
from twilio.rest import Client
from twilio.base.exceptions import TwilioRestException
from werkzeug.utils import secure_filename
from werkzeug.datastructures import  FileStorage
from s3_functions import s3upload_file
from werkzeug.utils import secure_filename

load_dotenv()
app = Flask(__name__)
app.secret_key = 'not-so-secret-key'
app.config.from_object('settings')
BUCKET = "lats-image-data"
UPLOAD_FOLDER = 'UPLOADS'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['UPLOAD_EXTENSIONS'] = ['jpg', 'png', 'jpeg']

TWILIO_ACCOUNT_SID = os.environ.get('TWILIO_ACCOUNT_SID')
TWILIO_AUTH_TOKEN= os.environ.get('TWILIO_AUTH_TOKEN')
VERIFY_SERVICE_SID= os.environ.get('VERIFY_SERVICE_SID')
client = Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)

KNOWN_PARTICIPANTS = app.config['KNOWN_PARTICIPANTS']

在文件的顶部,我们。

  • 导入了必要的Python模块和库,以便项目能够加载环境变量。
  • 从_settings.py_中导入参与者的列表。
  • 启动Flask应用程序。

一个随机字符串替换app.secret_key'的默认值not-so-secret-key 。Flask应用使用它是为了给用户会话提供有限的安全保障,也是因为我们需要存储用户的账户信息,并使用Flask的会话将其传递给网站上的其他路径。

在项目的根目录下创建一个名为_UPLOADS_的空文件夹。在本教程中,为了简单起见,所有上传的图片文件都将存放在这里。

为了组织项目目录,在项目的根目录下创建另一个名为_s3_functions_._py的_文件。这个文件将包含三个辅助函数,用于连接到AWS S3客户端并利用boto3库。

然后,在_s3_functions.py_文件中添加以下import 语句。

import boto3

创建HTML页面的模板文件夹 为了构建这个项目的用户界面,你将使用Flask模板。在工作目录中创建一个文件夹来存放它们,命名为templates,并在该文件夹中创建以下文件。

index.html:登陆页面,供用户输入他们的电子邮件地址和请求验证令牌。 verifypage.html:这是让用户在提示时输入验证码。 uploadpage.html:这是让用户提交.jpg、.png或.jpeg格式的图片。 success.html:这个页面显示上传图片的成功。 如果你使用macOS或Linux,请随意使用下面的命令来创建所有文件。

mkdir templates
touch templates/{index,success,uploadpage,verifypage}.html

如果你使用的是Microsoft Windows,请使用下面的命令。

mkdir templates
type nul >> "templates/index.html"
type nul >> "templates/success.html"
type nul >> "templates/uploadpage.html"
type nul >> "templates/verifypage.html"

建立用户登录页面

在这个项目中,用户将进入网站并输入他们的用户名,在这种情况下是一个电子邮件地址。复制并粘贴以下代码到你的_app.py_文件的底部。

@app.route('/', methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        username = request.form['username']
        if username in KNOWN_PARTICIPANTS:
            session['username'] = username
            send_verification(username)
            return redirect(url_for('verify_passcode_input'))
        error = "User not found. Please try again."
        return render_template('index.html', error=error)
    return render_template('index.html')

提出一个POST请求,让参与者的用户名存储在Flask会话中。如果用户名在数据库中,在这种情况下是在KNOWN_PARTICIPANTS 字典中,那么用户名就会存储在当前的Flask会话中,并将验证令牌发送到相应的电话号码中。参与者会被重定向到另一条路线,在那里他们会看到第二个表单,允许他们提交验证码。

通过复制和粘贴GitHub repo中的原始HTML表单到_index.html_文件中,创建一个接受用户名输入的表单,以及一个提交表单的按钮。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Request Verification Code</title>

  </head>
  <body>
    <form method="POST">
    <h1>Login</h1>
    {% if error %}
      <p class=error><strong>Error:</strong> {{ error }}
    {% endif %}
      <div class="field">
      <label class="label">Username</label>
      <input class="input" type="text" name="username" placeholder="Username">
      </div>
      <div class="field">
        <p class="control">
          <button type="submit" class="button is-success">
            Request verification code
          </button>
        </p>
      </div>
    </form>
  </body>
</html>

这是一个例子,说明当用户输入一个不在KNOWN_PARTICIPANTS 字典中的用户名时会发生什么。

localhost:5000 index login page with error message

用Twilio Verify生成一个验证码

设置好表单后,现在是有趣的部分了--调用Twilio Verify API!下一步是建立send_verification 函数,在用户提交表单后启动。它将在用户在数据库中输入一个有效的电子邮件后发送验证令牌。

在_app.py_文件中,在与login 函数相同的路由下添加以下代码。

@app.route('/', methods=['GET', 'POST'])

# ...

def send_verification(username):
    phone = KNOWN_PARTICIPANTS.get(username)
    client.verify \
        .services(VERIFY_SERVICE_SID) \
        .verifications \
        .create(to=phone, channel='sms')

Twilio客户端会向与当前Flask会话中存储的用户名相关的电话号码发送验证令牌。在这种情况下,指定的渠道是短信,但如果你愿意,也可以通过设置channel='voice' ,以通话的方式发送。

注意。请记住,这是一个发送验证密码的简单函数,还没有考虑到错误处理。

是时候测试一下了。在网页上,输入_settings.py_中与你的电话号码相对应的电子邮件。你应该很快就会收到一条带有密码的短信。

验证用户的电话号码

现在我们将从一个新的表单中获取用户的输入,并确保它与Twilio通过短信发到手机上的验证码完全相同。

让我们先在HTML方面创建表单。将我的GitHub repo中的HTML复制并粘贴到_verifypage.html_的正文中。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Verify Your Account</title>
  </head>
  <body>
    <h1 class="title">
      Please verify your account {{username}}
    </h1>
    {% if error %}
      <p class=error><strong>Error:</strong> {{ error }}
    {% endif %}
    <form method="POST">
      <div class="field">
        <label class="label">Enter the code sent to your phone number.</label>
        <input class="input" type="password" name="verificationcode" placeholder="verificationcode">
        </p>
      </div>
      <div class="field">
        <p class="control">
          <button type="submit" class="is-success" value="submitcode">
            Submit Verification Code
          </button>
        </p>
      </div>
    </form>
  </body>
</html>

但是,等等--如果Twilio是发送代码的,我们如何验证6位数的代码?我们需要定义/verifyme 路线,并定义相应的函数,以便用户可以验证密码。

复制并粘贴以下代码到_app.py_文件的底部。

@app.route('/verifyme', methods=['GET', 'POST'])
def verify_passcode_input():
    username = session['username']
    phone = KNOWN_PARTICIPANTS.get(username)
    error = None
    if request.method == 'POST':
        verification_code = request.form['verificationcode']
        if check_verification_token(phone, verification_code):
            return render_template('uploadpage.html', username = username)
        else:
            error = "Invalid verification code. Please try again."
            return render_template('verifypage.html', error=error)
    return render_template('verifypage.html', username=username)

我们需要在verify_passcode_input() 代码的下面定义check_verification_token() 函数,这样这个函数就可以在这个路由中被调用。

def check_verification_token(phone, token):
    check = client.verify \
        .services(VERIFY_SERVICE_SID) \
        .verification_checks \
        .create(to=phone, code=token)    
    return check.status == 'approved'

check_verification_token 函数接收Flask会话的电话号码和用户在文本框中输入的verification_code ,并调用Verify API以确保他们正确输入了一次性密码。

一旦用户提交了表单,然后向/verifyme 路径发出POST 请求,就会调用verify_passcode_input() 函数。如果密码是正确的,就会呈现出成功页面。与登录页面的逻辑类似,如果参与者输入了_错误的_验证码,页面会刷新并显示错误信息;页面也会让用户再次输入验证码。

允许用户提交照片

在这一点上,用户已经正确地输入了他们的凭证和验证码。现在是建立用户可以拖放图片文件的页面的时候了。从GitHub repo复制并粘贴下面的HTML到_uploadpage.html_的正文中。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Upload an image to the AWS S3 Bucket</title>
  </head>
  <body>
    <h1 class="title">
      Please upload an image in .jpg, .png, or .jpeg format
    </h1>
    {% if error %}
      <p class=error><strong>Error:</strong> {{ error }}
    {% endif %}
    <form action="/uploader" method="POST" enctype="multipart/form-data">
      <input type="file" name="file" />
      <br>
      <br>
      <input type=submit value=Upload>
    </form>   
  </body>
</html>

你可能已经注意到了,_uploadpage.html_页面中的机制是不同的,因为你必须指定这个POST请求中预期的输入类型。这里,multipart/form-data ,以便将数据编码为一个文件元素。

一旦用户点击提交按钮,他们就会被转到网站的/uploader 页面,如果他们上传了一个适当的文件,扩展名为_.jpg、.png或.jpeg_,他们就会看到一个成功页面。否则,他们将被要求重新上传一个有效的文件。

下面是错误信息的样子。

localhost page with error message saying "please upload a valid file"

回到_app.py_文件,建立这两条新路线,以便用户可以上传图片。复制并粘贴以下代码到文件的底部。

@app.route('/upload')
def upload_file():
   return render_template('uploadpage.html')

@app.route('/uploader', methods=['GET', 'POST'])
def submitted_file():
   username = session['username']
   if request.method == 'POST':
      f = request.files['file']
      if f and allowed_file(f.filename):
        user_secure_filename = secure_filename(f.filename)
        f.save(os.path.join(UPLOAD_FOLDER, user_secure_filename))
        s3_key = f"uploads/{user_secure_filename}"
        s3upload_file(s3_key, BUCKET)
        return render_template('success.html')
      else:
        error = "Please upload a valid file."
        return render_template('uploadpage.html', username = username, error = error)

如果用户在_uploadpage.html_上发出了POST ,那么文件就会被储存在Flask会话的request 对象中。我们不仅要检查用户是否上传了一个有效的_.jpg_、.png 或_.jpeg_文件,以及该文件是否存在,而且还要确保用户的输入是合适的。

这就是我们先前导入werkzeug 库的原因,这样我们就可以利用secure_filename 函数。我们的项目将上传的文件保存在项目目录内,所以我们必须采取预防措施,识别可能危害我们系统的文件名。

为了检查文件的扩展名,我们需要定义allowed_file 函数,上传的文件名可以被解析并与app.config['UPLOAD_EXTENSIONS'] 。向上滚动到_app.py_文件的顶部,定义一个全局函数。

将以下代码放在第一个/ 路由和KNOWN_PARTICIPANTS 的定义之间。

def allowed_file(filename):
   return '.' in filename and filename.rsplit('.', 1)[1].lower() in app.config['UPLOAD_EXTENSIONS']

@app.route('/', methods=['GET', 'POST'])
def login():
# ...

一旦文件输入被检查和批准,该文件将被保存到项目目录的 "UPLOADS "文件夹中,如app.config['UPLOAD_FOLDER']

处理上传至云端数据库的文件

如上所述,媒体文件被保存到工作目录中的本地_uploads_文件夹,然后调用另一个名为s3upload_file() 的函数。这个文件接收最近添加的文件的路径名,并将其插入第二个参数中提供的桶名中。上传完成后,页面被刷新,用户最终回到了登陆页面。

再次打开_s3_functions.py_文件,编写s3upload_file() 函数,完成/upload 路线。在import 语句下复制并粘贴以下代码。

def s3upload_file(file_name, bucket):
    object_name = file_name
    s3_client = boto3.client('s3')
    response = s3_client.upload_file(file_name, bucket, object_name)
    return response

创建一个s3_client 对象来启动一个代表亚马逊简单存储服务(S3)的低级客户端。在创建与S3的连接后,客户端对象使用upload_file() 函数,并接收filename 的路径,以找出要上传到桶中的媒体文件。最后一个参数,object_name ,代表媒体文件将被存储为S3桶中的密钥。

显示一个成功信息

现在你可以随心所欲地把他们重定向到其他地方,但在本教程中,你要把他们重定向到一个成功页面。从我的 GitHub repo复制并粘贴HTML到_模板_目录中的_success.html_ 文件。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Successful Upload!</title>
  </head>
  <body>
    <div class="container">
      <h1 class="title">
        Your picture has been successfully uploaded to the S3 bucket. 
      </h1>
    </div>
  </body>
</html>

用Twilio验证你的账户,并提交一张图片

现在是测试该应用程序的时候了。请随意查看GitHub上的完整代码。通过使用flask run ,确保Flask在你的终端上运行。然后访问 [http://localhost:5000/](http://localhost:5000/)并输入_settings.py_中定义的字典中的任何用户名。

我将使用"twilioisthebest@twilio.com"的电子邮件,这是我自己的电话号码的密钥,用于测试。

localhost login page

检查你的手机,看看Twilio Verify提供的验证码的通知。在我的例子中,该代码是864831。

notification with verification code 864831

localhost asking to verify the account with a code sent to the phone number

正确输入代码后,你会看到这个页面。

localhost page saying please upload an image in .jpg, .png, or .jpeg format

选择一个_.jpg、.png或.jpeg_格式的图片。请随意使用经典的_DRAW_THE_OWL_MEME.png_。点击上传按钮,检查项目目录下的_uploads_文件夹。

success page saying "your picture has been successfully uploaded to the S3 bucket"

检查你的项目目录并查看_UPLOADS_文件夹,或你创建的用于存储图片的任何文件夹。你应该看到你刚刚提交的图片。

检查上传文件的Amazon S3桶

在网页浏览器中打开一个新标签,回到AWS控制台。导航到S3桶,点击用于上传媒体文件的桶名。在这一点上,该桶中应该有一个对象,即_uploads_文件夹。

这里有一个为本文创建的 "lats-image-data "桶的例子。

Amazon S3 bucket dashboard listing the objects present in the bucket

点击_uploads_文件夹的链接。应该有一个新的对象列表。上面的列表显示了文件对象的名称,DRAW_THE_OWL_MEME.png,以及该对象的元数据,包括_文件类型、最后修改日期、大小和存储类别_。

Amazon S3 bucket dashboard listing the name of file objects in the bucket

多么成功啊!媒体文件已经成功上传,你可以选择下载该文件。

下一步是如何验证用户上传媒体文件到云端的?

祝贺你实施了安全的做法,并将安全措施纳入你的项目中!有很多方法可以扩展这个项目,建立一个完整的网站,与用户安全地互动,避免你可能遇到的不良行为者。

另一种使用Twilio Verify进行认证的方式是使用Twilio Verify和SendGrid通过电子邮件发送一个验证码。在这种情况下,你会使用数据库中的用户名或用户资料中的任何电子邮件地址。

你也可以通过在你的项目中实现图像识别API来检查用户的输入,以检测NSFW照片等内容,从而增加安全量。

如果你已经准备好将应用程序暴露给世界,请查看这3个在云端安装Python网络应用程序的技巧,或者阅读如何将一个网站重定向到另一个域名