Django Authentication 使用者認證系統完全指南 | Django 教學

2026/06/18 2026/05/24
Django Authentication 使用者認證系統完全指南 | Django 教學

幾乎所有的 Web 應用程式都需要處理使用者身份驗證。Django 內建了一套功能完善的 Authentication(認證) 系統,從 User 模型登入登出 函數、到 密碼管理密碼重設 流程,全部開箱即用。本篇將帶你全面了解 Django 認證系統的每個環節,並實作一套完整的使用者認證功能。

Django 認證系統概覽

Django 的認證系統由 django.contrib.auth 模組提供,它整合了 認證(Authentication)授權(Authorization) 兩大功能:

  • 認證(Authentication):驗證「你是誰」——使用者是否為合法帳號
  • 授權(Authorization):決定「你能做什麼」——使用者擁有哪些權限

要使用認證系統,確認 settings.py 中已包含以下設定:

# settings.py
INSTALLED_APPS = [
    'django.contrib.auth',            # 認證框架核心
    'django.contrib.contenttypes',    # 權限系統依賴
    # ...
]

MIDDLEWARE = [
    'django.contrib.sessions.middleware.SessionMiddleware',       # Session 支援
    'django.contrib.auth.middleware.AuthenticationMiddleware',    # 將 user 掛到 request
    # ...
]

認證系統的核心元件:

元件說明
User內建使用者模型,提供帳號、密碼、Email 等欄位
PermissionModel 層級的權限(add、change、delete、view)
Group權限的集合,可批次指派給使用者
Session基於 Session 的登入狀態維護機制

User 模型欄位

Django 的內建 User 模型(django.contrib.auth.models.User)提供了以下欄位:

欄位類型說明
usernameCharField使用者名稱(唯一)
passwordCharField雜湊後的密碼
emailEmailField電子郵件
first_nameCharField
last_nameCharField
is_activeBooleanField帳號是否啟用
is_staffBooleanField是否可登入 Admin 後台
is_superuserBooleanField是否為超級使用者
last_loginDateTimeField最後登入時間
date_joinedDateTimeField帳號建立時間

常用的方法:

from django.contrib.auth.models import User

# 建立一般使用者
user = User.objects.create_user(
    username='alice',
    email='alice@example.com',
    password='secure_password123'  # 自動雜湊處理
)

# 建立超級使用者
admin = User.objects.create_superuser(
    username='admin',
    email='admin@example.com',
    password='admin_password123'
)

# 檢查使用者屬性
user.is_authenticated  # True(已登入的使用者永遠為 True)
user.is_anonymous      # False
user.get_full_name()   # 回傳 "first_name last_name"
user.get_short_name()  # 回傳 "first_name"

authenticate / login / logout 函數

Django 提供三個核心函數來處理認證流程,它們位於 django.contrib.auth 模組中。

authenticate()——驗證帳號密碼

from django.contrib.auth import authenticate

# 驗證使用者憑證
user = authenticate(request, username='alice', password='secure_password123')

if user is not None:
    # 驗證成功,user 是一個 User 物件
    print(f"歡迎,{user.username}!")
else:
    # 驗證失敗(帳號不存在或密碼錯誤)
    print("帳號或密碼錯誤")

authenticate() 會依序嘗試 settings.pyAUTHENTICATION_BACKENDS 列出的所有認證後端,任一成功即回傳 User 物件。

login()——建立登入狀態

from django.contrib.auth import login

# 驗證成功後,建立 Session 登入狀態
login(request, user)
# 此時 Session 中已記錄使用者資訊
# 後續請求的 request.user 會自動指向此使用者

login() 做的事情是:將 User 的 ID 寫入 Session,並在 Response 中設定 sessionid Cookie,後續請求就能透過 Cookie 識別使用者身份。

logout()——登出

from django.contrib.auth import logout

# 清除 Session,登出使用者
logout(request)
# 此時 request.user 會變成 AnonymousUser

完整登入 View 範例

# views.py
from django.contrib.auth import authenticate, login, logout
from django.shortcuts import render, redirect

def login_view(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']

        # 第一步:驗證帳號密碼
        user = authenticate(request, username=username, password=password)

        if user is not None:
            # 第二步:建立登入狀態
            login(request, user)
            # 第三步:重導向到原始頁面或首頁
            next_url = request.GET.get('next', '/')
            return redirect(next_url)
        else:
            return render(request, 'accounts/login.html', {
                'error': '帳號或密碼錯誤'
            })

    return render(request, 'accounts/login.html')

def logout_view(request):
    if request.method == 'POST':
        logout(request)
        return redirect('login')
    return redirect('/')

@login_required 裝飾器

@login_required 是最常用的認證裝飾器,它會在 View 執行前自動檢查使用者是否已登入。未登入的使用者會被重導向到登入頁面。

from django.contrib.auth.decorators import login_required

@login_required
def dashboard(request):
    """只有已登入的使用者才能存取此頁面"""
    return render(request, 'accounts/dashboard.html', {
        'user': request.user
    })

# 自訂登入頁面 URL
@login_required(login_url='/custom-login/')
def profile(request):
    return render(request, 'accounts/profile.html')

重導向行為:

  1. 未登入使用者造訪 /dashboard/
  2. 被重導向到 LOGIN_URL(預設 /accounts/login/),URL 帶有 ?next=/dashboard/
  3. 使用者登入成功後,自動跳回 /dashboard/

settings.py 中設定相關的重導向 URL:

# settings.py
LOGIN_URL = '/accounts/login/'            # 未登入時重導向的目標
LOGIN_REDIRECT_URL = '/dashboard/'        # 登入成功後的預設重導向
LOGOUT_REDIRECT_URL = '/'                 # 登出後的重導向目標

在 CBV 中使用 LoginRequiredMixin

如果你使用 Class-Based Views(CBV) ,可以使用 LoginRequiredMixin

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView

class DashboardView(LoginRequiredMixin, TemplateView):
    template_name = 'accounts/dashboard.html'
    login_url = '/accounts/login/'  # 可選,預設使用 settings.LOGIN_URL

注意:LoginRequiredMixin 必須放在 第一個 繼承位置,才能正確攔截未登入的請求。


LoginView / LogoutView CBV

Django 提供了內建的 LoginViewLogoutView ,讓你不用自己寫認證邏輯,只需要設定 URL 和模板即可。

LoginView

# urls.py
from django.contrib.auth.views import LoginView

urlpatterns = [
    path('accounts/login/', LoginView.as_view(
        template_name='accounts/login.html',     # 自訂模板
        redirect_authenticated_user=True,         # 已登入使用者自動跳轉
    ), name='login'),
]

對應的模板只需要提供一個 form:

{# templates/accounts/login.html #}
<h2>登入</h2>

{% if form.errors %}
  <p style="color: red;">帳號或密碼錯誤,請重試。</p>
{% endif %}

<form method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <button type="submit">登入</button>
</form>

LogoutView

# urls.py
from django.contrib.auth.views import LogoutView

urlpatterns = [
    path('accounts/logout/', LogoutView.as_view(
        next_page='/',  # 登出後重導向到首頁
    ), name='logout'),
]
{# 在模板中使用 POST 請求登出 #}
<form method="post" action="{% url 'logout' %}">
  {% csrf_token %}
  <button type="submit">登出</button>
</form>

Django 4.1 以後,LogoutView 預設只接受 POST 請求,不再支援 GET 登出,這是為了防止 CSRF 攻擊(跨站請求偽造)


密碼管理

Django 提供了完善的密碼管理機制,包括密碼的設定、驗證與雜湊處理。

set_password() 與 check_password()

from django.contrib.auth.models import User

user = User.objects.get(username='alice')

# 設定新密碼(自動雜湊,不是存明碼)
user.set_password('new_secure_password')
user.save()  # 記得要呼叫 save()

# 驗證密碼是否正確
user.check_password('new_secure_password')   # True
user.check_password('wrong_password')         # False

重要提醒:永遠不要直接賦值 user.password = '...',這樣會存入明碼。必須使用 set_password() 方法,它會自動進行雜湊處理。

密碼雜湊機制

Django 使用 PBKDF2 演算法作為預設的密碼雜湊方式,儲存格式為 <algorithm>$<iterations>$<salt>$<hash>

pbkdf2_sha256$600000$randomsalt$hashed_value_here

你可以在 settings.py 中自訂使用的雜湊演算法:

# settings.py
PASSWORD_HASHERS = [
    # 第一個為新密碼的預設演算法
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',       # 預設
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.Argon2PasswordHasher',        # 推薦(需 pip install argon2-cffi)
    'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',  # 需 pip install bcrypt
]

密碼驗證器

Django 內建四個密碼驗證器,確保使用者設定的密碼符合安全標準:

# settings.py
AUTH_PASSWORD_VALIDATORS = [
    {
        # 密碼不能與使用者屬性(username、email 等)太相似
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        # 密碼最短長度
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        'OPTIONS': {'min_length': 8},
    },
    {
        # 密碼不能是常見弱密碼(內建 20,000 組常見密碼清單)
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        # 密碼不能全部是數字
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

密碼重設流程

Django 內建完整的密碼重設(Password Reset)流程,由四個 View 組成。你只需設定 URL 與模板,無需自己處理 token 產生與驗證邏輯。

設定四個 URL

# urls.py
from django.contrib.auth import views as auth_views

urlpatterns = [
    # 第一步:輸入 Email 頁面
    path('password-reset/', auth_views.PasswordResetView.as_view(
        template_name='accounts/password_reset.html',
        email_template_name='accounts/password_reset_email.html',
        subject_template_name='accounts/password_reset_subject.txt',
        success_url='/password-reset/done/',
    ), name='password_reset'),

    # 第二步:Email 已寄出的提示頁面
    path('password-reset/done/', auth_views.PasswordResetDoneView.as_view(
        template_name='accounts/password_reset_done.html',
    ), name='password_reset_done'),

    # 第三步:點擊連結後的重設表單頁面
    path('password-reset-confirm/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(
        template_name='accounts/password_reset_confirm.html',
        success_url='/password-reset-complete/',
    ), name='password_reset_confirm'),

    # 第四步:重設完成的提示頁面
    path('password-reset-complete/', auth_views.PasswordResetCompleteView.as_view(
        template_name='accounts/password_reset_complete.html',
    ), name='password_reset_complete'),
]

對應模板

{# templates/accounts/password_reset.html #}
<h2>重設密碼</h2>
<p>請輸入您的 Email,我們將寄送密碼重設連結。</p>
<form method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <button type="submit">寄送重設連結</button>
</form>
{# templates/accounts/password_reset_email.html(Email 內容模板)#}
您好 {{ user.get_username }}
請點擊以下連結重設您的密碼:
{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}

此連結僅可使用一次,若您未要求重設密碼,請忽略此信件。
{# templates/accounts/password_reset_confirm.html #}
<h2>設定新密碼</h2>
{% if validlink %}
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">確認新密碼</button>
  </form>
{% else %}
  <p>此重設連結已失效,請重新申請。</p>
{% endif %}

註冊功能實作

Django 沒有提供內建的註冊 View,但提供了 UserCreationForm 表單類別,讓你快速實作使用者註冊功能。

使用 UserCreationForm

# views.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login
from django.shortcuts import render, redirect

def register_view(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            # 儲存新使用者
            user = form.save()
            # 註冊成功後自動登入
            login(request, user)
            return redirect('dashboard')
    else:
        form = UserCreationForm()

    return render(request, 'accounts/register.html', {'form': form})

擴展 UserCreationForm 加入 Email 欄位

預設的 UserCreationForm 只有 username 和 password 欄位。若需要 Email 欄位,可以繼承並擴展:

# forms.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django import forms

class CustomUserCreationForm(UserCreationForm):
    email = forms.EmailField(
        required=True,
        help_text='請輸入有效的電子郵件地址'
    )

    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']

    def clean_email(self):
        """檢查 Email 是否已被使用"""
        email = self.cleaned_data.get('email')
        if User.objects.filter(email=email).exists():
            raise forms.ValidationError('此 Email 已被註冊')
        return email

    def save(self, commit=True):
        user = super().save(commit=False)
        user.email = self.cleaned_data['email']
        if commit:
            user.save()
        return user
# views.py
from .forms import CustomUserCreationForm

def register_view(request):
    if request.method == 'POST':
        form = CustomUserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()
            login(request, user)
            return redirect('dashboard')
    else:
        form = CustomUserCreationForm()

    return render(request, 'accounts/register.html', {'form': form})

對應的模板:

{# templates/accounts/register.html #}
<h2>建立帳號</h2>
<form method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <button type="submit">註冊</button>
</form>
<p>已有帳號?<a href="{% url 'login' %}">前往登入</a></p>

Session 安全性設定

認證系統依賴 Session 維護登入狀態,確保 Session 的安全性非常重要:

# settings.py
SESSION_COOKIE_HTTPONLY = True       # 防止 JavaScript 讀取 Cookie
SESSION_COOKIE_SECURE = True         # 只透過 HTTPS 傳送(生產環境)
SESSION_COOKIE_SAMESITE = 'Lax'     # 防止 CSRF 攻擊
SESSION_COOKIE_AGE = 1209600         # Session 有效期 14 天(單位:秒)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False  # 關閉瀏覽器後 Session 不失效

總結

Django 的 Authentication 系統功能完善且開箱即用,大幅降低了實作使用者認證的工作量。以下整理本篇的核心要點:

  1. 認證系統架構 整合了 User 模型、Permission、Group 與 Session,提供從登入到權限控制的完整解決方案
  2. authenticate / login / logout 三個核心函數各司其職——驗證憑證、建立登入狀態、清除 Session
  3. @login_required 裝飾器與 LoginRequiredMixin 讓存取控制變得簡單,搭配 LOGIN_URL 設定可自訂重導向行為
  4. LoginView / LogoutView 是 Django 內建的認證 CBV,只需設定模板和 URL 就能快速上線
  5. 密碼管理 透過 set_passwordcheck_password 處理,Django 自動進行雜湊,永遠不存明碼
  6. 密碼重設流程 由四個內建 View 組成,包含 token 產生與驗證,只需撰寫模板即可使用
  7. 註冊功能 透過 UserCreationForm 快速實作,可繼承擴展以加入自訂欄位

掌握了認證系統後,下一篇我們將深入探討 自訂使用者模型(Custom User Model) ,學習如何透過 AbstractUserAbstractBaseUser 打造符合業務需求的使用者模型。

BenZ Software Developer

熱愛技術的軟體開發者,在這裡分享程式開發經驗與學習筆記。