在 Web 應用程式開發中,使用者帳戶管理是至關重要的環節。本文將詳細介紹如何使用 Django 框架構建安全可靠的使用者驗證系統,包含使用者註冊、登入、登出、密碼管理以及多因素驗證等核心功能。我們將逐步說明每個流程的實作細節,並提供程式碼範例和測試策略,協助開發者打造更安全的 Web 應用程式。從使用者提交登入檔單開始,伺服器端會建立一個尚未啟用的帳戶,並傳送啟用信件到使用者提供的電子郵件地址。使用者需點選信件中的連結才能啟用帳戶,以防止惡意使用者盜用他人信箱註冊。
使用者註冊工作流程
使用者註冊工作流程的第一步是使用者提交登入檔單,包含使用者名稱、電子郵件地址和密碼。伺服器建立一個非活躍帳戶,重定向使用者到註冊確認頁面,並傳送帳戶啟用電子郵件。
使用者不能登入這個帳戶,因為帳戶尚未啟用。使用者必須驗證電子郵件地址以啟用帳戶,這可以防止惡意使用者使用他人的電子郵件地址建立帳戶。
Django 建立塊
在開始編寫程式碼之前,讓我們定義一些 Django 網頁開發的建立塊:
- 檢視(Views):檢視是用於處理 HTTP 請求的 Python 函式。檢視負責建立和傳回 HTTP 回應物件。
- 模型(Models):模型是用於將物件導向的應用程式與關聯式資料函式庫連線起來的類別。模型類別類似於資料函式庫表格,模型類別屬性類似於資料函式庫表格欄位,模型物件類似於資料函式庫表格中的行。
- 範本(Templates):範本是用於表示 HTTP 回應的 HTML 檔案和簡單的範本語法。檢視通常使用範本來組合靜態和動態內容。
Django 應用程式架構
Django 應用程式使用模型-檢視-範本(MVT)架構來處理請求。這個架構與模型-檢視-控制器(MVC)架構類似,但有一些不同之處。
- 模型(Model):模型是物件導向的應用程式和關聯式資料函式庫之間的物件關係對映層。
- 檢視(View):檢視是用於處理 HTTP 請求的 Python 函式,負責建立和傳回 HTTP 回應物件。
- 範本(Template):範本是用於表示 HTTP 回應的 HTML 檔案和簡單的範本語法。
安裝 django-registration
要使用 django-registration,請在虛擬環境中執行以下命令:
pip install django-registration
內容解密:
- 使用者註冊工作流程是兩步驟的過程:使用者建立帳戶,然後啟用帳戶。
- Django 的模型-檢視-範本架構用於處理請求。
- django-registration 是一個用於處理使用者註冊和登入的 Django 應用程式。
圖表翻譯:
flowchart TD A[使用者提交登入檔單] --> B[伺服器建立非活躍帳戶] B --> C[伺服器傳送帳戶啟用電子郵件] C --> D[使用者驗證電子郵件地址] D --> E[伺服器啟用帳戶]
這個圖表顯示了使用者註冊工作流程的過程。使用者提交登入檔單,伺服器建立非活躍帳戶,然後傳送帳戶啟用電子郵件。使用者驗證電子郵件地址,伺服器啟用帳戶。
安裝和設定 Django-Registration
要使用 Django-Registration,首先需要安裝它。可以使用 pipenv 來安裝:
$ pipenv install django-registration
接下來,需要在 Django 專案的設定檔中新增 django-registration。這需要在 INSTALLED_APPS
設定中新增 'django_registration'
:
INSTALLED_APPS = [
...
'django_registration',
]
然後,需要執行資料函式庫遷移命令來建立必要的資料函式庫表:
$ python manage.py migrate
接下來,需要在 Django 專案的 URL 組態檔中新增 django-registration 的 URL 組態。需要在 urls.py
檔中新增以下程式碼:
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('django_registration.backends.activation.urls')),
]
這會將 django-registration 的 URL 組態新增到 Django 專案中。
URL 組態對映
django-registration 提供了五個 URL 組態,對映到不同的檢視。以下是 URL 組態對映:
URL 路徑 | django-registration 檢視 |
---|---|
/accounts/activate/complete/ | TemplateView |
/accounts/activate/<activation_key>/ | ActivationView |
/accounts/register/ | RegistrationView |
/accounts/register/complete/ | TemplateView |
/accounts/register/closed/ | TemplateView |
其中,三個 URL 組態對映到 TemplateView
類別,這些檢視不執行任何邏輯,只是渲染範本。在下一節中,會建立這些範本。
Django 範本引擎設定
Django 專案中,範本引擎是一個強大的工具,能夠將靜態 HTML 和動態內容結合起來,生成動態網頁。要設定範本引擎,需要在設定模組中進行組態。
設定範本引擎
首先,需要在設定模組中匯入 os
模組。然後,找到 TEMPLATES
設定,這是一個範本引擎的列表。找到第一個範本引擎的 DIRS
鍵,這個鍵告訴範本引擎在哪些目錄中查詢範本檔案。新增以下程式碼,告訴範本引擎在 templates
目錄中查詢範本檔案:
import os
TEMPLATES = [
{
...
'DIRS': [os.path.join(BASE_DIR, 'templates')],
...
}
]
建立範本目錄
在專案根目錄下,建立一個名為 templates
的子目錄。然後,在 templates
目錄下,建立一個名為 django_registration
的子目錄。這是 django-registration 檢視預期找到範本的地方。
建立使用者註冊範本
在 django_registration
目錄下,建立一個名為 registration_form.html
的檔案。這個範本將渲染使用者登入檔單。以下是程式碼:
<html>
<body>
<form method='POST'>
{% csrf_token %}
{{ form.as_p }}
<button type='submit'>註冊</button>
</form>
</body>
</html>
建立註冊完成範本
在同一目錄下,建立一個名為 registration_complete.html
的檔案。這個範本將渲染一個簡單的確認頁面,當使用者成功註冊後:
<html>
<body>
註冊完成!
</body>
</html>
這些範本將被用於使用者註冊工作流程中。下一步,需要組態 django-registration 檢視,以使用這些範本。
使用 Django 建立使用者註冊和登入系統
8.1 使用者註冊
使用者註冊是網站的基本功能,允許使用者建立自己的帳戶。在這個章節中,我們將使用 Django 建立一個使用者註冊系統。
8.1.1 建立使用者登入檔單
首先,讓我們建立一個使用者登入檔單。這個表單將包含使用者名稱稱、電子郵件、密碼和密碼確認等欄位。
# forms.py
from django import forms
from django.contrib.auth.models import User
class UserRegistrationForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('username', 'email')
8.1.2 建立使用者註冊檢視
接下來,讓我們建立一個使用者註冊檢視。這個檢視將處理使用者登入檔單的提交。
# views.py
from django.shortcuts import render, redirect
from django.contrib.auth import login
from .forms import UserRegistrationForm
def register(request):
if request.method == 'POST':
user_form = UserRegistrationForm(request.POST)
if user_form.is_valid():
new_user = user_form.save(commit=False)
new_user.set_password(user_form.cleaned_data['password'])
new_user.save()
login(request, new_user)
return redirect('dashboard')
else:
user_form = UserRegistrationForm()
return render(request, 'account/register.html', {'user_form': user_form})
8.1.3 建立使用者註冊範本
最後,讓我們建立一個使用者註冊範本。這個範本將顯示使用者登入檔單。
<!-- register.html -->
<h1>使用者註冊</h1>
<form method="post">
{{ user_form.as_p }}
<button type="submit">註冊</button>
</form>
8.2 使用者登入
使用者登入是網站的另一個基本功能,允許使用者登入自己的帳戶。在這個章節中,我們將使用 Django 建立一個使用者登入系統。
8.2.1 使用 Django 的內建登入檢視
Django 提供了一個內建的登入檢視,讓我們可以輕鬆地建立一個使用者登入系統。
# urls.py
from django.urls import path
from django.contrib.auth import views as auth_views
urlpatterns = [
path('login/', auth_views.LoginView.as_view(), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]
8.2.2 建立使用者登入範本
最後,讓我們建立一個使用者登入範本。這個範本將顯示使用者登入表單。
<!-- login.html -->
<h1>使用者登入</h1>
<form method="post">
{{ form.as_p }}
<button type="submit">登入</button>
</form>
這樣就完成了使用者註冊和登入系統的建立。現在,使用者可以建立自己的帳戶並登入網站。
建立 Django 應用程式
在 Django 中,應用程式(app)是指一個自包含的模組,負責處理特定的功能或業務邏輯。要建立一個新的 Django 應用程式,可以使用以下命令:
python manage.py startapp profile_info
這個命令會在目前的目錄下建立一個新的目錄,名為 profile_info
,這個目錄包含了基本的 Django 應用程式結構。
Django 應用程式結構
一個典型的 Django 應用程式結構如下:
profile_info/
__init__.py
admin.py
apps.py
models.py
tests.py
views.py
migrations/
__init__.py
__init__.py
:一個空的檔案,表示這個目錄是一個 Python 套件。admin.py
:定義了應用程式的管理介面。apps.py
:定義了應用程式的組態。models.py
:定義了應用程式的資料模型。tests.py
:包含了應用程式的測試案例。views.py
:定義了應用程式的檢視函式。migrations/
:包含了資料函式庫遷移的相關檔案。
建立檢視
在 views.py
檔案中,可以定義檢視函式來處理 HTTP 請求。例如,可以建立一個檢視函式來顯示使用者的個人資訊:
# profile_info/views.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
@login_required
def profile_info(request):
return render(request, 'profile_info.html')
這個檢視函式使用 @login_required
裝飾器來確保只有登入的使用者才能存取這個檢視。
建立 URL 組態
要將檢視函式對映到 URL,可以在 urls.py
檔案中定義 URL 組態。例如,可以在 profile_info
應用程式中建立一個 urls.py
檔案:
# profile_info/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('profile_info/', views.profile_info, name='profile_info'),
]
然後,在主應用程式的 urls.py
檔案中,需要包含 profile_info
應用程式的 URL 組態:
# project/urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
path('profile_info/', include('profile_info.urls')),
]
這樣就可以透過 URL http://localhost:8000/profile_info/profile_info/
存取 profile_info
檢視函式。
建立 Django 應用程式
在 Django 中,應用程式是指一個自包含的模組,提供特定的功能。要建立一個新的 Django 應用程式,可以使用以下命令:
python manage.py startapp profile_info
這將建立一個名為 profile_info
的新應用程式,包含基本的目錄結構和檔案。
目錄結構
新建立的應用程式的目錄結構如下:
profile_info/
__init__.py
admin.py
apps.py
models.py
tests.py
views.py
templates/
registration/
login.html
profile.html
urls.py
在這個結構中,views.py
檔案包含應用程式的檢視邏輯,templates
目錄包含 HTML 範本,urls.py
檔案定義了 URL 路徑與檢視的對應關係。
檢視邏輯
在 views.py
檔案中,定義了一個名為 ProfileView
的檢視類別。這個檢視類別負責處理使用者的個人資料請求。
from django.http import HttpResponse
from django.shortcuts import render
from django.views.generic import View
class ProfileView(View):
def get(self, request):
user = request.user
if not user.is_authenticated:
return HttpResponse(status=401)
return render(request, 'profile.html')
這個檢視類別使用 request.user
屬性來存取使用者物件。如果使用者未經過驗證,檢視將傳回 401 狀態碼,否則將渲染 profile.html
範本。
URL 路徑
在 urls.py
檔案中,定義了 URL 路徑與檢視的對應關係。
from django.urls import path
from . import views
urlpatterns = [
path('profile/', views.ProfileView.as_view(), name='profile'),
]
這個 URL 路徑將 ProfileView
檢視對應到 /profile/
路徑。
範本
在 templates
目錄中,建立了兩個 HTML 範本:login.html
和 profile.html
。
<!-- login.html -->
<html>
<body>
<form method='POST'>
{% csrf_token %}
{{ form.as_p }}
<button type='submit'>Login</button>
</form>
</body>
</html>
<!-- profile.html -->
<html>
<body>
<p>{{ user }}</p>
<p><a href="{% url 'logout' %}">Logout</a></p>
</body>
</html>
login.html
範本包含了一個表單,允許使用者提交登入請求。profile.html
範本則顯示使用者的個人資料和登出連結。
多因素驗證(MFA)簡介
多因素驗證(MFA)是一種強化使用者身份驗證的方法,需要使用者提供多於一種驗證方式,例如密碼、生物特徵、手機驗證碼等。這種方法可以有效地防止密碼被盜用或猜測,提高使用者帳戶的安全性。
多因素驗證的工作原理
多因素驗證的工作原理是要求使用者提供多種不同的驗證方式,例如:
- 密碼:使用者的密碼是第一個驗證因素。
- 生物特徵:使用者的指紋、面部識別、聲音識別等生物特徵可以作為第二個驗證因素。
- 手機驗證碼:使用者的手機可以接收驗證碼,作為第二個驗證因素。
- U2F鑰匙:U2F鑰匙是一種硬體令牌,需要使用者物理上插入電腦才能驗證身份。
多因素驗證的優點
多因素驗證有以下優點:
- 提高安全性:多因素驗證可以有效地防止密碼被盜用或猜測。
- 降低風險:多因素驗證可以降低使用者帳戶被攻擊的風險。
- 符合法規要求:多因素驗證可以符合一些法規要求,例如PCI DSS、HIPAA等。
實作多因素驗證的方法
實作多因素驗證的方法有以下幾種:
- 使用第三方函式庫或框架:例如Django的django-otp、Flask的Flask-OTP等。
- 自行實作:可以使用Python的相關函式庫,例如pyotp、google-authenticator等,自行實作多因素驗證。
多因素驗證的實踐
以下是多因素驗證的實踐例子:
from django.contrib.auth import login
from django.contrib.auth.views import LoginView
from django_otp.decorators import otp_required
class MFALoginView(LoginView):
def form_valid(self, form):
user = form.get_user()
if user.is_authenticated:
# 啟用多因素驗證
if not user.has_otp():
return redirect('mfa_setup')
# 驗證使用者的OTP
if not user.verify_otp(request.POST.get('otp')):
return redirect('mfa_login')
return super().form_valid(form)
# 啟用多因素驗證的設定
MFA_REQUIRED = True
實作多重因素驗證(MFA)和要求驗證
在網站安全方面,多重因素驗證(MFA)是一個重要的機制,能夠有效地防止未經授權的存取。除了使用密碼外,MFA還需要使用者提供其他形式的驗證,例如一次性密碼(OTP)、生物特徵認證(如指紋或面部識別)等。
一次性密碼(OTP)
一次性密碼是一種臨時的密碼,通常透過手機或其他裝置接收。這種驗證方式可以有效地防止密碼被竊取或猜測。
生物特徵認證
生物特徵認證是一種使用使用者的生物特徵(如指紋、面部等)進行驗證的方式。這種方式可以提供更高的安全性,但也需要相應的硬體和軟體支援。
多重因素驗證的實作
在實作多重因素驗證時,需要注意以下幾點:
- 不要自己實作安全功能:安全功能的實作需要非常高的專業知識和經驗,自己實作可能會導致安全漏洞。
- 避免使用不安全的驗證方式:例如,透過簡訊或語音郵件傳送一次性密碼是不安全的,因為電話網路可能被攻擊。
- 避免使用容易被猜測的安全問題:例如,“你母親的孃家姓氏是什麼?”或“你小學時的最好朋友是誰?”這些問題容易被攻擊者猜測。
要求驗證
在網站中,需要對使用者進行驗證,以確保只有授權的使用者才能存取受限資源。Django提供了一個名為LoginRequiredMixin
的類別,可以方便地實作這個功能。
使用LoginRequiredMixin
LoginRequiredMixin
是一個類別,繼承自View
。當檢視繼承自LoginRequiredMixin
時,Django會自動驗證使用者是否登入。如果使用者沒有登入,Django會重定向到登入頁面。
以下是使用LoginRequiredMixin
的示例:
from django.views.generic import View
from django.contrib.auth.mixins import LoginRequiredMixin
class ProfileView(LoginRequiredMixin, View):
def get(self, request):
# 只有登入的使用者才能存取這個檢視
return render(request, 'profile.html')
使用login_required
裝飾器
login_required
是LoginRequiredMixin
的函式式等價物。可以使用@login_required
裝飾器來限制存取函式式檢視。
from django.contrib.auth.decorators import login_required
@login_required
def profile_view(request):
# 只有登入的使用者才能存取這個檢視
return render(request, 'profile.html')
使用 Django 進行身份驗證測試
在 Django 中,測試身份驗證是一個重要的步驟,以確保您的應用程式的安全性和正確性。下面,我們將介紹如何使用 Django 的測試框架來測試身份驗證。
建立測試使用者
首先,我們需要建立一個測試使用者。這可以透過 get_user_model()
函式來完成。下面的程式碼建立了一個名為 “bob” 的使用者,密碼為 “wool reselect resurface annuity”。
from django.contrib.auth import get_user_model
passphrase = 'wool reselect resurface annuity'
get_user_model().objects.create_user('bob', password=passphrase)
測試身份驗證工作流程
接下來,我們可以測試身份驗證工作流程。這包括登入、存取使用者個人頁面和登出。下面的程式碼展示瞭如何使用 self.client
物件來模擬這些操作。
from django.test import TestCase
class TestAuthentication(TestCase):
def test_authenticated_workflow(self):
# 建立測試使用者
passphrase = 'wool reselect resurface annuity'
get_user_model().objects.create_user('bob', password=passphrase)
# 登入
self.client.login(username='bob', password=passphrase)
# 存取使用者個人頁面
response = self.client.get('/accounts/profile/', secure=True)
# 驗證回應
self.assertEqual(200, response.status_code)
self.assertContains(response, 'bob')
# 登出
self.client.logout()
測試匿名存取限制
另外,我們還需要測試匿名存取限制。這可以透過嘗試匿名存取使用者個人頁面來完成。下面的程式碼展示瞭如何測試這個場景。
class TestAuthentication(TestCase):
def test_prohibit_anonymous_access(self):
# 嘗試匿名存取使用者個人頁面
response = self.client.get('/accounts/profile/', secure=True)
# 驗證回應
self.assertRedirects(response, '/accounts/login/?next=/accounts/profile/')
密碼管理的重要性
在前面的章節中,我們學習瞭如何建立和啟用使用者賬戶,如何實作使用者登入和登出。然而,密碼管理是使用者賬戶安全的另一個重要方面。在本章中,我們將學習如何實作密碼變更、驗證和重置功能。
從使用者經驗與安全性的雙重角度來看,建構一個完善的使用者註冊和登入系統至關重要。本文深入探討了從使用者註冊流程、Django 框架的 MVT 架構、django-registration 套件的應用,到使用者身份驗證測試及密碼管理等一系列關鍵環節。分析 Django 的檢視、模型和範本如何協同工作,實作使用者資料的動態呈現,並特別關注 URL 組態與範本引擎的設定,以確保系統的穩定運作。同時,文章也點明瞭多因素驗證(MFA) 的重要性,及其在提升系統安全層級上的顯著作用,並以一次性密碼和生物特徵驗證等方式,強化了帳戶防護機制。然而,任何安全措施都並非完美無缺,持續的測試和最佳化,例如文中提到的身份驗證測試,才能確保系統的安全性與可靠性。展望未來,隨著資安威脅的日益複雜,整合更進階的驗證機制和更嚴密的密碼管理策略,將是使用者帳戶安全的重要發展方向。對於開發團隊而言,持續關注並應用新的安全技術,才能有效保障使用者資訊安全,並提升平臺的信賴度。