0

Tùy chỉnh cấu hình xác thực người dùng trong Django

image.png

Vấn đề

  • Trong Django đã có sẵn một hệ thống đăng nhập mặc định (dùng tên đăng nhậpmật khẩu).
  • Tuy nhiên với các bài toán khác nhau thì không phải lúc nào nó cũng đúng được (Ví dụ như đăng nhập bằng email, hoặc thêm bớt các field trong bảng users,...)

Cách giải quyết

  • Cũng có khá nhiều cách giải quyết. Bạn có thể không dùng ứng dụng django.contrib.authdjango.contrib.sessions, tự xây dựng một hệ thống xác thực riêng cho mình, một middleware để hỗ trợ parse user vào request. (Về cách này mình sẽ có một bài chi tiết về nó sau)

  • Trong bài viết này mình sẽ hướng dẫn bạn chỉnh lại User Model trong django.contrib.auth.models


Các bước thực hiện

#1. Tạo ra User Model

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

class User(AbstractBaseUser):
    # Authentication
    username = None
    email = models.EmailField(max_length=128, unique=True, db_index=True)
    
    # Permission
    is_staff = models.BooleanField(default=False)

    # User information
    name = models.CharField(max_length=128, default='User')

    USERNAME_FIELD = "email"

    class Meta:
        db_table = "users"

Mình sẽ giải thích một tí về nó

  • Trước hết mình tạo ra một class User được thừa kế từ AbstractBaseUser để dùng lại được các phương thức liên quan đến mã hóa mật khẩu, quản lý session, ...

  • Mình không dùng username để đăng nhập nên mình xóa field đó đi bằng cách cho nó bằng None

  • Mình dùng email để đăng nhập nên mình tạo ra một field email với ràng buộc duy nhất (unique).

  • Mình cần tạo ra một tài khoản có thể login vào trang Django admin nên mình tạo ra field is_staff. Nếu nó bằng True thì sẽ cho phép truy cập.

    • Tuy nhiên nếu bạn không dùng trang Django admin, bạn có thể bỏ qua nó
  • Mình thêm một vài thông tin người dùng như tên người dùng - field name

  • Để hệ thống biết được là mình sẽ đăng nhập bằng email chứ không phải username mình chỉ định USERNAME_FIELD

  • Cuối cùng là mình chỉ định tên bảng sẽ là users ở tùy chọn db_table

-- Tuy nhiên mình lại custom hơi quá tay nên user manager mặc định không còn phù hợp nữa. Thế là mình chuyển qua bước 2.


#2. Tạo User Manager

from django.contrib.auth.models import BaseUserManager

class UserManager(BaseUserManager):
    def create_user(self, email: str, password: str, **extra_fields):
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, email: str, password: str, **extra_fields):
        extra_fields.setdefault("is_staff", True)
        return self.create_user(email=email, password=password, **extra_fields)

Ở đây mình có 2 hàm

  • create_user: Đây là hàm tạo user bình thường.

    • Ban đầu mình mình khởi tạo một thực thể User (self.model) và gán email cùng extra_fields (những field còn lại không bắt buộc phải có)
    • Tiếp đến mình dùng hàm set_password để mã hóagán mật khẩu đã mã hóa cho user
    • Cuối cùng là mình sẽ commit với cơ sở dữ liệu và trả về user đã tạo
  • create_superuser: Đây là hàm tạo user với quyền quản trị

    • Ở đây mình chỉ để đơn giản là quản trị viên được phép vô trang Django Admin nên mình set is_staff thành True trước kia tạo user.
    • Tại đây bạn cũng có thể gán vài trò (role) và quyền hạn (permission) tùy theo nghiệp vụ dự án của bạn.

Sau khi tạo xong mình gán UserManager vào User Model

class User(AbstractBaseUser):
    ...
    # Config
    objects = UserManager()
    ...

#3. Tạo migrations và migrate database

  • Tạo migrations bằng lệnh

    python manage.py makemigrations
    
  • Migrate bằng lệnh

    python manage.py migrate
    
    • Ở đây đôi khi sẽ xuất hiện lỗi conflic migrationskhông thể migrate, vì bạn đã migrate model user cũ trước đó. Mình thường giải quyết quyết bằng cách xóa toàn bộ bảng trong database và tiến hành migrate lại.

#4. Đăng ký User Model mới với hệ thống

  • Bạn mở file settings.py và thêm một tùy chọn
    # Custom User Model
    AUTH_USER_MODEL = "<tên app>.User"
    

Kiểm tra kết quả

Giờ có thể vào database để xem cấu trúc bảng và chạy lệnh tạo superuser để kiểm tra kết quả

python manage.py createsuperuser

Tài liệu tham khảo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí