แผนการเรียนรู้
/

Authentication: ระบบยืนยันตัวตนผู้ใช้

สร้างระบบ Login/Register ที่ปลอดภัยด้วย Django Authentication

ผลการเรียนรู้

  • อธิบายรูปแบบการจัดเก็บข้อมูลผู้ใช้โดย Django ได้
  • ประยุกต์ใช้ความรู้เพื่อสร้างฟอร์มในการรับลงทะเบียนผู้ใช้ใหม่ได้
  • ประยุกต์ใช้ความรู้เพื่อสร้างฟอร์มในการตรวจสอบผู้ใช้เข้าใช้งานได้

เนื้อหาหลัก

  • Authentication: การยืนยันตัวตนผู้ใช้
  • Authorization: การกำหนดสิทธิ์การเข้าถึง
  • Django Authentication System: ระบบ authentication ที่มาพร้อมกับ Django
  • User Model: Model ที่เก็บข้อมูลผู้ใช้
  • Authentication Forms: Form สำหรับ Login และ Register
  • Password Hashing: การเก็บ password อย่างปลอดภัย
  • Session Management: การจัดการ session ของผู้ใช้
  • Permissions: การกำหนดสิทธิ์การเข้าถึงส่วนต่างๆ ของ application

Agenda

  • ทำความเข้าใจ Django Authentication System
  • สร้าง User Registration Form
  • สร้าง Login Form
  • จัดการ User Sessions
  • ใช้ Password Hashing เพื่อเก็บ Password อย่างปลอดภัย
  • กำหนด Permissions เพื่อควบคุมการเข้าถึง
  • ตัวอย่างการใช้งานจริง และ Workshop

Django Authentication System: ภาพรวม

ทำความเข้าใจส่วนประกอบสำคัญของ Django Authentication System

User Model

  • เก็บข้อมูลผู้ใช้ (username, password, email, first_name, last_name)
  • Django มี AbstractUser และ AbstractBaseUser ให้ inherit
  • สามารถสร้าง custom User model ได้

Authentication Backend

  • ตรวจสอบ username/password
  • Django มี ModelBackend เป็น default
  • สามารถสร้าง custom authentication backends ได้

Permissions and Groups

  • กำหนดสิทธิ์การเข้าถึง resources ต่างๆ
  • Permissions กำหนดให้กับ User หรือ Group
  • Group คือกลุ่มของ User ที่มีสิทธิ์เหมือนกัน

Middleware

  • AuthenticationMiddleware เพิ่ม request.user attribute
  • SessionMiddleware จัดการ session ของผู้ใช้
  • ต้องใส่ใน MIDDLEWARE setting

Custom User Model: ข้อมูลผู้ใช้ที่ยืดหยุ่น

ปรับแต่ง User model เพื่อเพิ่ม fields ที่ต้องการ

ทำไมต้อง Custom User Model?

  • เพิ่ม fields ที่จำเป็นสำหรับ application ของคุณ (เช่น phone_number, birthdate)
  • เปลี่ยน authentication field (default คือ username)
  • ควบคุมการจัดการ user ได้อย่างละเอียด

การสร้าง Custom User Model

  • Inherit จาก AbstractUser หรือ AbstractBaseUser
  • กำหนด fields เพิ่มเติม
  • กำหนด USERNAME_FIELD (field ที่ใช้ login)
  • กำหนด REQUIRED_FIELDS (fields ที่ต้องกรอกตอน createsuperuser)

ตัวอย่าง Custom User Model

                          
from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    phone_number = models.CharField(max_length=15, blank=True)
    birthdate = models.DateField(null=True, blank=True)

    USERNAME_FIELD = 'email'   # ใช้ email ในการ login
    REQUIRED_FIELDS = ['username', 'first_name', 'last_name']

    def __str__(self):
        return self.email
                          
                      

ข้อควรจำ

  • ต้องกำหนด AUTH_USER_MODEL ใน settings.py
  • ทำ makemigrations และ migrate หลังจากสร้าง custom user model

Registration Form: สร้างบัญชีผู้ใช้ใหม่

สร้าง form เพื่อรับข้อมูลและสร้างบัญชีผู้ใช้ใหม่

Registration Form (myapp/forms.py)

                          
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from myapp.models import CustomUser

class CustomUserCreationForm(UserCreationForm):

    class Meta:
        model = CustomUser
        fields = ('username', 'email', 'phone_number')  # fields ที่ต้องการใน form

class CustomUserChangeForm(UserChangeForm):

    class Meta:
        model = CustomUser
        fields = ('username', 'email', 'phone_number')
                          
                      

View (myapp/views.py)

                          
from django.shortcuts import render, redirect
from myapp.forms import CustomUserCreationForm

def register_view(request):
    if request.method == 'POST':
        form = CustomUserCreationForm(request.POST)
        if form.is_valid():
            form.save()  # สร้าง user ใหม่
            return redirect('login')  # Redirect ไปหน้า login
    else:
        form = CustomUserCreationForm()
    return render(request, 'register.html', {'form': form})
                          
                      

Template (register.html)

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

สิ่งที่ต้องจำ

  • ตรวจสอบว่าได้กำหนด AUTH_USER_MODEL ใน settings.py แล้ว
  • ตรวจสอบว่าได้ทำ makemigrations และ migrate แล้ว
  • ใส่ {% csrf_token %} ใน template form เสมอเพื่อป้องกัน CSRF attacks

Login Form: ตรวจสอบผู้ใช้เข้าใช้งาน

สร้าง form เพื่อตรวจสอบ username/password และให้ผู้ใช้เข้าใช้งาน

Login Form (myapp/forms.py)

                          
from django import forms
from django.contrib.auth.forms import AuthenticationForm

class LoginForm(AuthenticationForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['username'].widget.attrs.update({'class': 'form-control'})
        self.fields['password'].widget.attrs.update({'class': 'form-control'})
                          
                      

* Inherit จาก AuthenticationForm
* สามารถปรับแต่ง widgets ของ fields ได้

View (myapp/views.py)

                          
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from .forms import LoginForm

def login_view(request):
    if request.method == 'POST':
        form = LoginForm(request, data=request.POST)
        if form.is_valid():
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password')
            user = authenticate(username=username, password=password)
            if user is not None:
                login(request, user)
                return redirect('home')  # Redirect ไปหน้า home
            else:
                return render(request, 'login.html', {'form': form, 'error': 'Invalid username or password'})
    else:
        form = LoginForm()
    return render(request, 'login.html', {'form': form})
                          
                      

* ใช้ authenticate() เพื่อตรวจสอบ username/password
* ใช้ login() เพื่อสร้าง session ให้กับ user
* Redirect ไปยังหน้า home หาก login สำเร็จ

Template (myapp/templates/myapp/login.html)

                          
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Login</button>
    {% if error %}
      <p style="color:red">{{ error }}</p>
    {% endif %}
</form>
                          
                      

Logout: ออกจากระบบ

สร้าง view สำหรับ logout ผู้ใช้

View (myapp/views.py)

                          
from django.shortcuts import redirect
from django.contrib.auth import logout

def logout_view(request):
    logout(request)
    return redirect('home')  # Redirect ไปหน้า home
                          
                      

* ใช้ logout() เพื่อ clear session ของผู้ใช้
* Redirect ไปยังหน้า home หลังจาก logout

URL Configuration (urls.py)

                          
from django.urls import path
from . import views

urlpatterns = [
    path('logout/', views.logout_view, name='logout'),
]
                          
                      

* Map URL /logout/ ไปยัง view function logout_view

Template (home.html หรือ template อื่นๆ)

                          
<a href="{% url 'logout' %}">Logout</a>
                          
                      

* สร้าง link ไปยังหน้า logout โดยใช้ {% url 'logout' %}

Require Login: บังคับให้ Login ก่อนเข้าใช้งาน

จำกัดการเข้าถึงบาง view โดยบังคับให้ผู้ใช้ต้อง login ก่อน

Using the login_required Decorator (FBV)

                          
from django.shortcuts import render
from django.contrib.auth.decorators import login_required

@login_required
def my_protected_view(request):
    # code ที่ต้องการการ login
    return render(request, 'protected.html')
                          
                      

* ใช้ @login_required decorator เพื่อบังคับให้ผู้ใช้ต้อง login ก่อนเข้า view นี้ * หากผู้ใช้ยังไม่ได้ login จะถูก redirect ไปยังหน้า login (default: /accounts/login/)

Using the LoginRequiredMixin (CBV)

                          
from django.views.generic import View
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render

class MyProtectedView(LoginRequiredMixin, View):
    def get(self, request):
        # code ที่ต้องการการ login
        return render(request, 'protected.html')
                          
                      

* ใช้ LoginRequiredMixin เพื่อบังคับให้ผู้ใช้ต้อง login ก่อนเข้า view นี้ * Inherit LoginRequiredMixin ก่อน View

Settings (settings.py)

                          
LOGIN_REDIRECT_URL = 'home'  # หน้าที่จะ redirect ไปหลังจาก login สำเร็จ
LOGIN_URL = 'login' # ชื่อ url pattern ของหน้า login
                          
                      

* กำหนด LOGIN_REDIRECT_URL เพื่อกำหนดหน้าที่จะ redirect ไปหลังจาก login สำเร็จ * กำหนด LOGIN_URL เพื่อกำหนด URL pattern ของหน้า login

Password Hashing: เก็บ Password อย่างปลอดภัย

เรียนรู้วิธีการเก็บ Password อย่างปลอดภัยโดยใช้ Password Hashing

Password Hashing คืออะไร?

  • การแปลง password เป็น string ที่ไม่สามารถย้อนกลับได้
  • ป้องกันการถูกขโมย password หากฐานข้อมูลถูก compromised
  • ใช้ algorithm ที่แข็งแรง (เช่น bcrypt, PBKDF2)

Django Password Hashing

  • Django ใช้ PBKDF2 เป็น default password hashing algorithm
  • Password จะถูก hashing โดยอัตโนมัติเมื่อ save user
  • ไม่ต้อง implement เอง

การตรวจสอบ Password

                          
from django.contrib.auth import authenticate

user = authenticate(username='myuser', password='mypassword')
if user is not None:
    # Login สำเร็จ
    pass
else:
    # Login ไม่สำเร็จ
    pass
                          
                      

* ใช้ authenticate() function เพื่อตรวจสอบ password
* Django จะตรวจสอบ password โดยใช้ hashing algorithm เดียวกัน

Role-Based Authentication (RBA)

ควบคุมการเข้าถึงด้วย Roles แทน Users

RBA คืออะไร?

  • กำหนดสิทธิ์การเข้าถึงโดยอิงจาก Roles (บทบาท) ของผู้ใช้
  • แต่ละ Role มีชุด Permissions (สิทธิ์) ที่แตกต่างกัน
  • ผู้ใช้สามารถมีได้หลาย Role
  • ช่วยให้การจัดการสิทธิ์ง่ายขึ้นและเป็นระบบ

RBA vs Traditional Permission Management

  • Traditional: กำหนด Permissions ให้กับ User โดยตรง (จัดการยากเมื่อ User จำนวนมาก)
  • RBA: กำหนด Permissions ให้กับ Role และ Assign Role ให้ User (จัดการง่ายกว่า)

ประโยชน์ของ RBA

  • ง่ายต่อการจัดการสิทธิ์ (Assign Role แทน Assign Permission)
  • ลดความซับซ้อนในการกำหนดสิทธิ์
  • ปรับขนาดได้ง่าย (Scalable)
  • เพิ่มความปลอดภัย (Security)

RBA ใน Django: การ Implement

สร้าง Roles และ Permissions ใน Django

สร้าง Roles และ Permissions

                
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
from myapp.models import Article # สมมติว่ามี Model ชื่อ Article

# สร้าง Role "Editor"
editor_group = Group.objects.create(name='Editor')

# กำหนด Permission "can_edit_article" ให้กับ Role "Editor"
content_type = ContentType.objects.get_for_model(Article)
can_edit_article = Permission.objects.create(
    codename='can_edit_article',
    name='Can Edit Article',
    content_type=content_type,
)
editor_group.permissions.add(can_edit_article)
                
              

ตรวจสอบ Roles ใน Views

                
from django.contrib.auth.decorators import login_required, permission_required

@login_required
@permission_required('myapp.can_edit_article') # ต้องมี permission ถึงจะเข้าได้
def edit_article(request, article_id):
    # code สำหรับแก้ไข article
    pass
                
              

ตรวจสอบ Roles ใน Templates

                
{% if user.has_perm "myapp.can_edit_article" %}
  <a href="{% url 'edit_article' article.id %}">Edit</a>
{% endif %}
                
              

Workshop: Authentication System

สร้างระบบ Authentication ครบวงจร

Workshop Steps

  1. สร้าง Django project และ app (accounts)
  2. สร้าง Custom User Model (ถ้าต้องการ)
  3. สร้าง Registration Form
  4. สร้าง Login Form
  5. สร้าง Logout View
  6. Require Login สำหรับบาง View
  7. ปรับแต่ง Templates

Extra Challenges

  • Password Reset
  • Social Authentication (Google, Facebook)
  • Permissions Based Access Control

Resources