Penyesuaian pembuktian keaslian di Django

Pembuktian keaslian yang datang dengan Django adalah cukup bagus untuk kasus umum, tetapi anda mungkin tidak butuh memenuhi dengan awal out-of-the-box. Untuk menyesuaikan pembuktian keaslian ke proyek anda butuh melibatkan pemahaman titik apa dari sistem disediakan dapat di perpanjang atau diganti. Dokumen ini menyediakan rincian tentang bagaimana sistem pembuktian keaslian dapat di sesuaikan.

Authentication backends menyediakan sebuah sistem yang dapat diperpanjang untuk ketika nama pengguna dan sandi disimpan dengan model pengguna butuh untuk diotentifikasi terhadap layanan berbeda dari awalan Django.

Anda dapat memberikan model anda perizinan custom permissions yang dapat diperiksa melalui sistem otorisasi Django.

Anda dapat extend awalan model User, atau substitute sepenuhnya model disesuaikan.

Sumber pembuktian keaslian lain

Mungkin ada kali anda harus butuh mengait ke dalam sumber pembuktian keaslian lain -- yaitu, sumber lain dari nama pengguna dan sandi atau metode pembuktian keaslian.

Sebagai contoh, perusahaan anda mungkin sudah mempunyai pengaturan LDAP yang menyimpan nama pengguna dan sandi untuk setiap karyawan. Itu akan menjadi cekcok untuk kedua administrator jaringan dan pengguna nya sendiri jika pengguna mempunyai akun terpisah di LDAP dan aplikasi berbasis-Django.

Jadi, untuk menangani keadaan seperti ini, sistem pembuktian keaslian Django membiarkan anda memasang sumber pembuktian keaslian lain. Anda dapat menimpa skema berbasis-basisdata awal Django, atau anda dapat menggunakan sistem awal untuk dipasangkan dengan sistem lain.

Lihat authentication backend reference untuk informasi pada backend otentifikasi yang disertakan dengan Django.

Menentukan backend pembuktian keaslian

Dibelakang layar, Django merawat daftar "backend pembuktian keaslian" yang dia periksa untuk pembuktian keaslian. Ketika seseorang memanggil django.contrib.auth.authenticate() -- seperti digambarkan di How to log a user in -- Django mencoba membuktikan keaslian disemua bakcend pembuktian keaslian itu. Jika metode pembuktian keaslian pertama gagal, Django mencoba yang kedua, dan selanjutnya, sampai semua backend telah dicoba.

Daftar backend pembuktian keaslian untuk digunakan ditentukan dalam pengaturan AUTHENTICATION_BACKENDS. Ini seharusnya daftar nama jalur Python yang menunjuk ke kelas Python yang mengetahui bagaimana membuktikan keaslian. Kelas ini dapat berada dimanapun di jalur Python anda.

Secara awal, AUTHENTICATION_BACKENDS disetel ke:

['django.contrib.auth.backends.ModelBackend']

Itu adalah backend pembuktian keaslian dasar yang memeriksa basisdata pengguna Django dan permintaan perizinan siap-pakai. Dia tidak menyediakan perlindungan terhadap serangan paksa brutal melalui mekanisme pembatasan apapun. Anda dapat salah satu menerapkan mekanisme pembatasan laju anda sendiri di backend pembuktian keaslian penyesuaian, atau menggunakan mekanisme yang disediakan oleh kebanyakan peladen Jaringan.

Urutan masalah AUTHENTICATION_BACKENDS, jadi jika nama pengguna dan sandi sama adalah sah di banyak backend, Django akan menghentikan pengolahan pada pertama yang positif cocok.

Jika backend memunculkan pengecualian PermissionDenied, pembuktian keaslian akan segera gagal. Django tidak akan memeriksa backend yang mengikuti.

Catatan

Sekali pengguna telah dibuktikan keasliannya, Django menyimpan backend mana yang telah digunakan untuk membuktikan keaslian pengguna di sesi pengguna, dan menggunakan kembali backend sama untuk lamanya sesi tersebut bilamana mengakses ke pengguna dibuktikan keasliannya saat ini dibutuhkan. Ini secara efektif berarti bahwa sumber pembuktian keaslian disimpan pada per sesi, jadi jika anda merubah AUTHENTICATION_BACKENDS, anda akan butuh membersihkan data sesi jika anda butuh memaksa pengguna membuktikan keaslian kembali menggunakan model berbeda. Cara sederhana untuk melakukan itu adalah mengjalankan Session.objects.all().delete().

Menulis backend pembuktian keaslian

Sebuah backend autentifikasi adalah sebuah kelas yang menerapkan dua metode wajib: get_user(user_id) dan authenticate(request, **credentials), dan juga kumpulan dari pilihan perizinan terhubung authorization methods.

Metode get_user mengambil sebuah user_id -- yang dapat berupa nama pengguna, ID basisdata atau apapun, tetapi harus primary key dari obyek pengguna anda -- dan mengembalikan sebuah obyek pengguna.

Metode authenticate mengambil argumen request dan mandat sebagai kata kunci. Kebanyakan dari waktu, dia akan kelihatan seperti ini:

class MyBackend(object):
    def authenticate(self, request, username=None, password=None):
        # Check the username/password and return a user.
        ...

Tetapi itu dapat juga membuktikan keaslian sebuah token, seperti begitu:

class MyBackend(object):
    def authenticate(self, request, token=None):
        # Check the token and return a user.
        ...

Salah satu cara, authenticate() harus memeriksa mandat yang dia dapatkan, dan dia harus mengembalikan obyek user yang cocok dengan mandat, jika mandat sah. Jika mereka tidak sah, dia harus mengembalikan None.

request adalah sebuah HttpRequest dan mungkin berupa None jika itu tidak disediakan pada authenticate() (yang melewatkan itu ke backend).

Admin Django erat ke Django User object. Cara terbaik berurusan dengna ini adalah membuat obyek user Django untuk setiap pengguna yang ada untuk backend anda (sebagai contoh dalam direktori LDAP, basisdata SQL eksternal anda, dll.) Anda dapat salah satu menulis tulisan untuk melakukannya terlebih dahulu, atau metode authenticate anda dapat melakukannya pertama kali pengguna masuk.

Ini adalah sebuah contoh yang membuktikan keaslian variabel terhdap nama pengguna dan sandi ditentukan dalam berkas settings.py anda dan membuat sebuah obyek User Django pertama kali pengguna dibuktikan keaslian:

from django.conf import settings
from django.contrib.auth.hashers import check_password
from django.contrib.auth.models import User

class SettingsBackend(object):
    """
    Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD.

    Use the login name and a hash of the password. For example:

    ADMIN_LOGIN = 'admin'
    ADMIN_PASSWORD = 'pbkdf2_sha256$30000$Vo0VlMnkR4Bk$qEvtdyZRWTcOsCnI/oQ7fVOu1XAURIZYoOZ3iq8Dr4M='
    """

    def authenticate(self, request, username=None, password=None):
        login_valid = (settings.ADMIN_LOGIN == username)
        pwd_valid = check_password(password, settings.ADMIN_PASSWORD)
        if login_valid and pwd_valid:
            try:
                user = User.objects.get(username=username)
            except User.DoesNotExist:
                # Create a new user. There's no need to set a password
                # because only the password from settings.py is checked.
                user = User(username=username)
                user.is_staff = True
                user.is_superuser = True
                user.save()
            return user
        return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None
Changed in Django 1.11:

Parameter request telah ditambahkan ke authenticate() dan dukungan untuk backend yang tidak menerima itu akan dipindahkan dalam Django 2.1.

Menangani otorisasi dalam backend penyesuaian

Penyesuaian backend sah dapat menyediakan perizinan mereka sendiri.

Model pengguna akan mengutus perizinan fungsi pencaian (get_group_permissions(), get_all_permissions(), has_perm(), dan has_module_perms()) ke backend pembuktian keaslian apapun yang menerapkan fungsi ini.

Perizinan diberikan ke pengguna akan menjadi duperset dari semua perizinan dikembalikan oleh semua backend. Yaitu, Django menghadiahkan sebuah perizinan kepada pengguna bahwa tiap satu hadiah backend.

Jika backend memunculkan pengecualian PermissionDenied di has_perm() atau has_module_perms(), otorisasi akan segera gagal dan Django tidak akan memeriksa backend yang mengikutinya.

Backend sederhana diatas dapat menerapkan periznan untuk admin ajaib cukup sederhana:

class SettingsBackend(object):
    ...
    def has_perm(self, user_obj, perm, obj=None):
        return user_obj.username == settings.ADMIN_LOGIN

Ini memberikan perizinan penuh kepada pengguna yang diberikan akses di contoh diatas. Perhatikan bahwa di penambahan ke argumen sama diberikan ke fungsi django.contrib.auth.models.User terkait, fungsi pembuktian keaslian backend semua mengambil obyek pengguna, yang mungkin menjadi pengguna anonim, sebagai sebuah argumen.

Penerapan otorisasi penuh dapat ditemukan dalam kelas ModelBackend di django/contrib/auth/backends.py, yang merupakan backend awal dan meminta tabel auth_permission kebanyakan waktu. Jika anda berharap untuk menyediakan kebiasaan penyesuaian untuk hanya bagian dari API backend, anda dapat mengambil keuntungan dari warisan Python dan subkelas ModelBackend dari menerapkan API lengkap di backend penyesuaian.

Otorisasi untuk pengguna anonim

Sebuah pengguna anonim adalah satu yang tidak dibuktikan keaslian yaitu mereka menyediakan rincian pembuktian keaslian yang tidak sah. Bagaimanapun, itu tidak dibutuhkan berarti mereka tidak diotorisasikan melakukan apapun. Pada kebanyakan tingkatan dasar, kebanyakan situs jaringan mengotorisasi pengguna anonim untuk menjelajahi kebanyakan situs, dan banyak mengizinkan pengguna memasang komentar dll.

Kerangka perizinan Django tidak mempunyai tempat untuk menyimpan perizinan untuk pengguna anonim. Bagaimanapun, obyek pengguna melewati backend pembuktian keaslian mungkin obyek django.contrib.auth.models.AnonymousUser, mengizinkan backend untuk menentukan kebiasaan otorisasi penyesuaian untuk pengguna anonim. Ini khususnya berguna untuk penulis dari aplikasi digunakan kembali, yang dapat menugaskan semua pertanyaan dan otorisasi ke backend pembuktian keaslian, daripada membutuhkan pengaturan, sebagai contoh, untuk mengendalikan akses anonim.

Otorisasi untuk pengguna tidak aktif

Seorang pengguna tidak aktif adalah satu yang mempunyai bidang is_active nya disetel menjadi False. Backend otentifikasi ModelBackend dan RemoteUserBackend melarang pengguna ini dari otentifikasi. Jika model pengguna penyesuaian tidak mempunyai bidang is_active, semua pengguna akan diizinkan untuk otentifikasi.

Anda dapat menggunakan AllowAllUsersModelBackend atau AllowAllUsersRemoteUserBackend jika anda ingin mengizinkan pengguna tidak aktif untuk diotentifikasi.

Dukungan untuk pengguna anonim di sistem perizinan mengizinkan untuk sebuah skenaria dimana pengguna anonim mempunyai perizinan untuk melakukan sesuatu selama pengguna dibuktikan keaslian tidak aktif tidak.

Jangan lupa untuk mencoba untuk atribut is_active dari pengguna di cara perizinan backend anda sendiri.

Changed in Django 1.10:

Di versi terlama, ModelBackend mengizinkan pengguna tidak aktif untuk diotentifikasi.

Penanganan perizinan obyek

Kerangka perizinan Django mempunyai sebuahyayasan untuk perizinan obyek, meskipun tidak ada penerapa untuknya didalam inti. Hal ini berarti bahwa memeriksa untuk perizinan obyek akan selalu mengembalikan False atau daftar kosong (tergantung pada penampilan pemeriksaan). Sebuah backend pembuktian keaslian akan menerima parameter katakunci obj dan user_obj untuk setiap obyek terkait cara otorisasi dan dapat mengembalikan tingkat perizinan obyek sewajarnya.

Penyesuaian perizinan

Untuk membuat perizinan penyesuaian untuk obyek model yang diberikan, gunakan permissions model Meta attribute.

Model task contoh ini membuat tiga perizinan penyesuaian, yaitu, tindakan pengguna dapat atau tidak dapat dilakukan dengan permintaan Task, khusus pada apliaksi anda:

class Task(models.Model):
    ...
    class Meta:
        permissions = (
            ("view_task", "Can see available tasks"),
            ("change_task_status", "Can change the status of tasks"),
            ("close_task", "Can remove a task by setting its status as closed"),
        )

Satu-satunya ini dilakukan adalah membuat perizinan tambahan ketika anda menjalankan manage.py migrate (fungsi yang membuat perizinan terhubung ke sinyal post_migrate). Kode anda bertanggung jawab dari pemeriksaan nilai perizinan ini ketika seorang pengguna mencoba mengakses fungsionalitas disediakan oleh aplikasi (melihat tugas, merubah keadaan dari tugas, menutup tugas.) Melanjutkan contoh diatas, pemeriksaan berikut jika sebuah pengguna mungkin melihat tugas:

user.has_perm('app.view_task')

Memperpanjang model User yang ada

Terdapat dua jalan untuk memperpanjang model User awal tanpa mengganti model milik anda. Jika perubahan anda butuhkan murni kebiasaan, dan tidak membutuhkan perubahan apapun ke apa ang disimpan di basisdata, anda dapat membuat proxy model berdasarkan pada User. Ini mengizinkan fitur apapun ditawarkan oleh model proxy termasuk pemesanan awal, pengelola penyesuaian, atau cara model penyesuaian.

Jika anda berharap menyimpan informasi terkait ke User, anda dapat menggunakan OneToOneField pada sebuah model mengandung bidang untuk informasi tambahan. Ini model satu-ke-satu selalu memanggil model profil, karena dia akan menyimpan informasi terkait bukan-asli tentang pengguna situs. Sebagai contoh anda mungkin membuat sebuah model Employee:

from django.contrib.auth.models import User

class Employee(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    department = models.CharField(max_length=100)

Mengganggap Pegawai Fred Smith yang ada yang mempunyai kedua model User dan Employee, anda dapat mengakses informasi terkait menggunakan standar Django ketentuan model terkait:

>>> u = User.objects.get(username='fsmith')
>>> freds_department = u.employee.department

Untuk menambahkan profil bidang model ke halaman pengguna dalam admin, tentukan sebuah class:~django.contrib.admin.InlineModelAdmin (untuk contoh ini, kami akan menggunakan StackedInline) di admin.py aplikasi anda dan menambahkannya ke kelas UserAdmin yang terdaftar dengan kelas User:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User

from my_user_profile_app.models import Employee

# Define an inline admin descriptor for Employee model
# which acts a bit like a singleton
class EmployeeInline(admin.StackedInline):
    model = Employee
    can_delete = False
    verbose_name_plural = 'employee'

# Define a new User admin
class UserAdmin(BaseUserAdmin):
    inlines = (EmployeeInline, )

# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)

Model profil ini tidak khusus dengan cara apapun - mereka hanya model Django yang terjadi untuk memiliki tautan one-to-one dengan model user. Dengan demikian, mereka tidak dibuat otomatis ketika pengguna dibuat, tetapi django.db.models.signals.post_save dapat digunakan untuk membuat atau memperbaharui model sewajarnya.

menggunakan hasil model terkait di tambahan permintaan atau penggabungan untuk mendapatkan data terkait. Tergantung pada kebutuhan anda, penyesuaian model user yang menyertakan bidang terkait mungkin pilihan terbaik anda, bagaimanapun hubungan yang ada pada model user awalan dalam aplikasi proyek anda mungkin membenarkan muatan basisdata lebih.

Mengganti model User penyesuaian

Beberapa macam proyek mungkin mempunyai persyaratan pembuktian keaslian untuk dimana model User siap-pakai Django tidak selalu sesuai. Sebagai contoh, pada beberapa situs akan masuk akal menggunakan sebuah alamat surel sebagai token pencirian daripada nama pengguna.

Django mengizinkan anda untuk menimpa model pengguna awalan dengan menyediakan nilai untuk pengaturan AUTH_USER_MODEL yang mengacu model penyesuaian:

AUTH_USER_MODEL = 'myapp.MyUser'

Pasangan titik ini menggambarkan nama dari aplikasi Django (yang harus berada di INSTALLED_APPS), dan nama dari model Django yang anda harapkan untuk digunakan sebagai model user anda.

Menggunakan model pengguna penyesuaian ketika memulai sebuah proyek

Jika anda sedang memulai proyek baru, sangat dianjurkan mengatur penyesuaian model user, bahkan jika awalan model User cukup untuk anda. Model kebiasaan ini mirip pada awalan model user, tetapi anda akan dapat menyesuaikan nya di masa depan jika kebutuhan muncul:

from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    pass

Jangan lupa menunjuk AUTH_USER_MODEL ke itu. Lakukan ini sebelum membuat perpindahan apapun atau menjalankan manage.py migrate untuk pertama kalinya.

Juga, daftar model dalam admin.py aplikasi:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User

admin.site.register(User, UserAdmin)

Merubah ke proyek-tengah penyesuaian model user

Merubah AUTH_USER_MODEL setelah anda membuat tabel-tabel basisdata adalah penting lebih sulit sejak itu mempengaruhi foreign key dan hubungan many-to-many, sebagai contoh.

Perubahan ini tidak dapat diselesaikan secara otomatis dan membutuhkan perbaikan secara manual skema anda, memindahkan data anda dari tabel user lama, dan kemungkinan secara manual memberlakukan kembali beberapa perpindahan. Lihat #25313 untuk ringkasan dari langkah-langkah.

Karena pembatasan dari fitur ketergantungan dinamis Django untuk model-model dapat ditukar, pengacuan model oleh AUTH_USER_MODEL harus dibuat di perpindahan pertama dari aplikasinya (biasanya dipanggil 0001_initial); sebaliknya, anda akan mempunyai masalah ketergantungan.

Sebagai tambahan, anda mungkin berjalan kedalam CircularDependencyError ketika menjalankan perpindahan anda sebagai Django tidak akan dapat secara otomatis memutus ketergantungan pada ketergantungan dinamis. Jika anda melihat kesalahan ini, anda harus memutuskan perulangan dengan memindahkan model bergantung pada model user anda kedalam perindahan kedua. (Anda dapat mencoba membuat dua model biasa yang memiliki ForeignKey ke setiap lainnya dan melihat bagaimana makemigrations mengatasi lingkaran ketergantungan jika anda ingin melihat bagaimana itu biasanya diselesaikan.)

Aplikasi digunakan kembali AUTH_USER_MODEL

Aplikasi dapat digunakan kembali tidak harus menerapkan penyesuaian model user. Sebuah proyek mungkin menggunakan banyak aplikasi, dan dua aplikasi dapat digunakan kembali yang menerapkan penyesuaian model user tidak dapat digunakan bersama-sama. Jika anda butuh menyimpan per informasi pengguna di aplikasi anda, gunakan ForeignKey atau OneToOneField pada settings.AUTH_USER_MODEL seperti yang digambarkan dibawah.

Mengacu model User

Jika anda mengacu User secara langsung (sebagai contoh, dengan mengacu ke itu di foreign key), kode anda tidak akan bekerja di proyek dimana pengaturan AUTH_USER_MODEL telah berubah ke model user berbeda.

get_user_model()[sumber]

Daripada mengacu ke User secara langsung, anda harus mengacu modl user menggunakan django.contrib.auth.get_user_model(). Metode ini akan mengembalikan model user aktif saat ini -- penyesuaian model user jika satu adalah ditentukan, atau User sebaliknya.

Ketika anda menentukan foreign key atau hubungan many-to-many pada model pengguna, anda harus menentukan model penyesuaian menggunakan pengaturan AUTH_USER_MODEL. Sebagai contoh:

from django.conf import settings
from django.db import models

class Article(models.Model):
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )

Ketika terhubung ke sinyal yang dikirim oleh model User. anda harus menentukan penyesuaian model menggunakan pengaturan AUTH_USER_MODEL. Sebagai contoh:

from django.conf import settings
from django.db.models.signals import post_save

def post_save_receiver(sender, instance, created, **kwargs):
    pass

post_save.connect(post_save_receiver, sender=settings.AUTH_USER_MODEL)

Secara umum, itu paling mudah mengacu ke model user dengan pengaturan AUTH_USER_MODEL dalam kode yang dijalankan pada waktu impor, bagaimanapun, itu juga memungkinkan memanggil get_user_model() selagi Django mengimpor model, jadi anda dapat menggunakan models.ForeignKey(get_user_model(), ...).

Jika aplikasi anda dicobakan dengan banyak model user, menggunakan @override_settings(AUTH_USER_MODEL=...) sebagai contoh, dan anda meng cache hasil dari get_user_model() dalam sebuah variabel tingkat-variabel, anda mungkin butuh mendengarkan pada sinyal setting_changed untuk membersihkan cache. Sebagai contoh:

from django.apps import apps
from django.contrib.auth import get_user_model
from django.core.signals import setting_changed
from django.dispatch import receiver

@receiver(setting_changed)
def user_model_swapped(**kwargs):
    if kwargs['setting'] == 'AUTH_USER_MODEL':
        apps.clear_cache()
        from myapp import some_module
        some_module.UserModel = get_user_model()
Changed in Django 1.11:

Kemampuan memanggil get_user_model() pada waktu impor telah ditambahkan.

Menentukan model pengguna penyesuaian

Pertimbangan rancangan model

Berpikir hati-hati sebelum menangani informasi tidak langsung terkait ke otentifikasi di model pengguna penyesuaian anda.

Itu mungkin lebih baik untuk menyimpan aplikasi-khusus informasi pengguna dalam sebuah model yang mempunyai hubungan dengan model user. Itu mengizinkan setiap aplikasi menentukan persyaratan data pengguna miliknya tanpa mempertaruhkan pertentangan dengan aplikasi lain. Di sisi lain, permintaan untuk mengambil informasi terkait ini akan melibatkan peggabungan basisdata, yang akan mempunyai pengaruh pada penampilan.

Django mengharapkan model pengguna penyesuaian anda memenuhi persyaratan minimal.

  1. Jika anda menggunakan backend pembuktian keaslian awal, kemudian model anda harus mempunyai bidang unik tunggal yang dapat digunakan untuk tujuan pencirian. Ini dapat berupa nama pengguna, sebuah alamat surel, atau atribut unik lainnya. Bidang nama pengguna tidak unik diizinkan jika anda menggunakan penyesuaian backend pembuktian keaslian yang dapat mendukungnya.
  2. Model anda harus menyediakan cara terbaik untuk mengalamatkan pengguna dalam bentuk "short" and "long". Penafsiran paling umum dari ini akan digunakan nama diberikan pengguna sebagai penciri "short", dan nama lengkap pengguna sebagai penciri "long". Bagaimanapun, tidak ada batasan pada apa yang duca cara ini kembalikan - jika anda ingin, mereka dapat mengembalikan nilai sama yang tepat.

Cara termudah untuk membangun selalu tunduk penyesuaian model user adalah mewarisi dari AbstractBaseUser. AbstractBaseUser menyediakan inti penerapan dari model user, termasuk sandi bercampur dan setel kembali sandi token. Anda harus kemudian menyediakan beberapa kunci penerapan rincian:

class models.CustomUser
USERNAME_FIELD

Deretan karakter menggambarkan nama dari bidang pada model user yang digunakan sebagai penciri unik. Ini akan biasanya berupa nama pengguna dari beberapa macam, tetapi itu dapat juga berupa alamat surel, atau apapun penciri unik lainnya. Bidang harus berupa unik (yaitu, mempunyai setelan unique=True di pengertiannya), meskipun anda menggunakan penyesuaian backend otentifikasi yang dapat mendukung nama pengguna bukan unik.

Dalam contoh berikut, bidang identifier digunakan sebagai bidang pengenal:

class MyUser(AbstractBaseUser):
    identifier = models.CharField(max_length=40, unique=True)
    ...
    USERNAME_FIELD = 'identifier'

REQUIRED_FIELD sekarang mendukung ForeignKey. Karena tidak mungkin melewatkan instance model selama meminta createsuperuser, kecuali pengguna memasukkan nilai dari nilai to_field (primary_key oleh awalan) dari instance yang ada.

EMAIL_FIELD
New in Django 1.11.

Sebuah string menggambarkan nama dari bidang surel pada model User. Nilai ini dikembalikan oleh get_email_field_name().

REQUIRED_FIELDS

Sebuah daftar dari nama bidang yang akan diminta ketika membuat sebuah pengguna melalui perintah pengelolaan createsuperuser. Pengguna akan diminta untuk menyediakan nilai untuk setiap bidang ini. Itu harus menyertakan bidang apapun yang blank adalah False atau tidak menentukan dan mungkin disertakan bidang tambahan anda ingin minta ketika sebuah pengguna dibuat secara interaktif. REQUIRED_FIELDS tidak mempunyai efek di bagian lagi dari Django, seperti membuat sebuah pengguna di admin.

Sebagai contoh, ini ada pengertian sebagian untuk model pengguna yang menentukan dua bidang wajib- tanggal lahir dan tinggi:

class MyUser(AbstractBaseUser):
    ...
    date_of_birth = models.DateField()
    height = models.FloatField()
    ...
    REQUIRED_FIELDS = ['date_of_birth', 'height']

Catatan

REQUIRED_FIELDS harus mengandung semua bidang diwajibkan pada model pengguna anda, tetapi tidak mengandung USERNAME_FIELD atau password ketika bidang ini selalu diminta.

REQUIRED_FIELDS sekarang mendukung ForeignKey. Karena tidak mungkin melewatkan instance model selama meminta createsuperuser, kecuali pengguna memasukkan nilai dari nilai to_field (primary_key oleh awalan) dari instance yang ada.

is_active

Sebuah atribut boolean yang mengindikasikan apakah pengguna dianggap "aktif". Atribut ini disediakan sebagai sebuah atribut pada AbstractBaseUser awalan pada True. Bagaimana anda memilih menerapkan itu akan tergantung pada rincian dari backend otentifikasi yang anda pilih. Lihat dokumentasi dari is_active attribute on the built-in user model untuk rincian.

get_full_name()

Penciri resmi terpanjang untuk pengguna. Pengartian umum akan berupa nama lengkap dari pengguna, tetapi itu dapat berupa deretan karakter apapun yang mencirikan pengguna.

get_short_name()

Pendek, pencitri tidak resmi untuk pengguna. Pengartian umum akan berupa nama pertama dari pengguna, tetapi itu dapat berupa deretan karakter apapun yang menciri pengguna di cara tidak resmi. Itu juga mungkin mengembalikan nilai sama sebagai django.contrib.auth.models.User.get_full_name().

Mengimpor AbstractBaseUser

AbstractBaseUser dan BaseUserManager dapat diimpor dari django.contrib.auth.base_user sehingga mereka dapat diimpor tanpa menyertakan django.contrib.auth di INSTALLED_APPS.

Atribut dan cara berikut tersedia pada setiap subkelas dari AbstractBaseUser:

class models.AbstractBaseUser
get_username()

Mengembalikan nilai dari bidang dicalonkan oleh USERNAME_FIELD.

clean()
New in Django 1.10.

Normalisasikan nama pengguna dengan memanggil normalize_username(). Jika anda menimpa cara ini, pastikan memanggil super() untuk menahan normalisasi.

classmethod get_email_field_name()
New in Django 1.11.

Mengembalikan nama dari bidang surel ditentukan oleh atribut EMAIL_FIELD. Awalan pada 'email' jika EMAIL_FIELD tidak ditentukan.

classmethod normalize_username(username)
New in Django 1.10.

Memberlakukan normalisasi Unicode NFKC pada nama pengguna sehingga nampak karakter mirip dengan titik kode Unicode berbeda dianggap mirip.

is_authenticated

Atribut hanya-baca yang selalu True (sebagai lawan AnonymousUser.is_authenticated yang selalu False). Ini adalah cara untuk memberitahu jika pengguna telah diotentifikasi. Ini tidak berarti perizinan apapun dan tidak memeriksa jika pengguna adalah aktif atau mempunyai sesi sah. Meskipun secara biasa anda akan memeriksa atribut ini pada request.user untuk menemukan apakah itu telah dikumpulkan oleh AuthenticationMiddleware (mewakili pengguna masuk saat ini), anda harus mengetahui atribut ini adalah True untuk tiap instance User.

Changed in Django 1.10:

Di versi terlama, ini adalah cara. Dukungan kesesuaian kebelakang mendukung untuk menggunakannya sebagai cara akan dipindahkan di Django 2.0.

is_anonymous

Atribut hanya-baca yaitu selalu False. Ini adalah jalan untuk membedakan obyek User and AnonymousUser. Umumnya, anda harus memilih menggunakan is_authenticated pada atribut ini.

Changed in Django 1.10:

Di versi terlama, ini adalah cara. Dukungan kesesuaian kebelakang mendukung untuk menggunakannya sebagai cara akan dipindahkan di Django 2.0.

set_password(raw_password)

Setel sandi pengguna ke deretan karakter mentah yang diberikan, merawat has sandi. Tidak menyimpan obyek AbstractBaseUser.

Ketika sandi mentah adalah None, sandi akan disetel ke sandi tidak biasa, seolah-olah set_unusable_password() digunakan.

check_password(raw_password)

Mengembalikan True jika deretan karakter mentah yang diberikan adalah sandi benar untuk pengguna. (Ini merawat hash sandi dalam membuat perbandingan.)

set_unusable_password()

Tandai pengguna sebagai mempunyai sandi tidak disetel. Ini tidak sama seperti memiliki deretan karakter kosong untuk sebuah sandi. check_password() untuk pengguna ini tidak akan pernah mengembalikan True. Tidak menyimpan obyek AbstractBaseUser.

Anda mungkin butuh ini jika otentifikasi untuk aplikasi anda memakan tempat terhadap sumber luar yang ada seperti pelipat LDAP.

has_usable_password()

Mengembalikan False jika set_unusable_password() telah dipanggil untuk pengguna ini.

get_session_auth_hash()

Mengembalikan nilai HMAC dari kolom kata sandi. Digunakan untuk Penghapusan sesi pada perubahan sandi.

AbstractUser subkelas AbstractBaseUser:

class models.AbstractUser
clean()
New in Django 1.11.

Normalisasikan surel dengan memanggil BaseUserManager.normalize_email(). Jika anda menimpa cara ini, pastikan memanggil super() untuk menahan normalisasi.

Anda harus juga menentukan penyesuaian pengelola untuk model user anda. Jika model user anda menentukan bidang username, email, is_staff, is_active, is_superuser, last_login, dan date_joined sama seperti pengguna awalan Django, anda dapat cukup memasang UserManager Django; bagaimanapun, jika model user anda menentukan bidang berbeda, anda akan butuh menentukan penyesuaian pengelola yang memperpanjang BaseUserManager menyediakan dua metode tambahan:

class models.CustomUserManager
create_user(*username_field*, password=None, **other_fields)

Sifat dari create_user() harus menerima bidang nama pengguna, ditambah semua bidang wajib sebagai argumen. Sebagai contoh, jika model pengguna anda menggunakan email sebagai bidang nama pengguna, dan mempunyai date_of_birth sebagai bidang wajib, kemudian create_user harus ditentukan sebagai:

def create_user(self, email, date_of_birth, password=None):
    # create user here
    ...
create_superuser(*username_field*, password, **other_fields)

Sifat dari create_superuser() harus menerima bidang nama pengguna, ditambah semua bidang wajib sebagai argumen. Sebagai contoh, jika model pengguna anda menggunakan email sebagai bidang nama pengguna, dan mempunyai date_of_birth sebagai bidang wajib, kemudian create_superuser harus ditentukan sebagai:

def create_superuser(self, email, date_of_birth, password):
    # create superuser here
    ...

Tidak seperti create_user(), create_superuser() harus membutuhkan pemanggil untuk menyedianan sebuah sandi.

BaseUserManager menyediakan cara kegunaan berikut:

class models.BaseUserManager
classmethod normalize_email(email)

Menormalkan alamat surel dengan menghuruf kecilkan bagian ranah dari alamat surel.

get_by_natural_key(username)

Mengambil instance pengguna menggunakan isi dari bidang dicalonkan oleh USERNAME_FIELD.

make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')

Mengembalikan sandi acak dengan panjang yang diberikan dan deretan karakter yang diberikan dari karakter yang diizinkan. Catat bahwa nilai awal dari allowed_chars tidak mengandung huruf yang dapat menyebabkan pengguna bingung, termasuk:

  • i, l, I, and 1 (huruf kecil i, huruf kecil L, huruf besar i, dan angka satu)
  • o, O, and 0 (huruf kecil o, huruf besar o, dan nol)

Memperpanjang User awal Django

Jika anda sepenuhnya senang dengan model User Django dan anda hanya ingin menambahkan beberapa informasi profil tambahan, anda dapat mensubkelaskan django.contrib.auth.models.AbstractUser dan menambah penyesuaian bidang profil anda, meskipun kami telah menganjurkan model terpisah seperti digambarkan di catatan "Model design considerations" dari Menentukan model pengguna penyesuaian. AbstractUser menyediakan penerapan penuh dari awalan User sebagai sebuah abstract model.

Penyesuaian pengguna dan formulir otentifikasi siap-pakai

SIap-pakai Django forms dan views membuat pendapat tertentu tentang model user yang mereka bekerja dengannya.

Bentuk berikut cocok dengan subkelas apapun dari AbstractBaseUser:

Formulir berikut membuat pendapat tentang model user dan dapat digunakan dengan adanya jika pendapat tersebut dipenuhi:

  • PasswordResetForm: Beranggapan bahwa model user mempunyai sebuah bidang yang menyimpan alamat surel pengguna dengan nama dikembalikan oleh get_email_field_name() (email secara awalan) yang dapat digunakan untuk mencirikan pengguna dan bidang boolean bernama is_active untuk mencegah penyetelan kembali sandi untuk pengguna tidak aktif.

Akhirnya, formulir berikut diikat pada User dan butuh ditulis kembali atau diperpanjang untuk bekerja dengan penyesuaian model user:

Jika penyesuaian model user anda adalah subkelas sederhana dari AbstractUser, kemudian anda dapat memperpanjang formulir ini di sikap ini:

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

class CustomUserCreationForm(UserCreationForm):

    class Meta(UserCreationForm.Meta):
        model = CustomUser
        fields = UserCreationForm.Meta.fields + ('custom_field',)

Penyesuaian pengguna dan django.contrib.admin

Jika anda ingin penyesuaian model user anda juga bekerja dengan admin, model user anda harus menentukan beberapa atribut dan metode tambahan. Cara ini mengizinkan admin mengendalikan akses user ke isi admin:

class models.CustomUser
is_staff

Mengembalikan True jika pengguna diizinkan mempunyai akses ke situs admin

is_active

Mengembalikan True jika akun pengguna saat ini aktif.

has_perm(perm, obj=None):

Mengembalikan True jika pengguna mempunyai perizinan nama. Jika obj disediakan, perizinan butuh diperiksa terhadap instace obyek tertentu.

has_module_perms(app_label):

Mengembalikan True jika pengguna mempunyai perizinan untuk mengakses model pada aplikasi yang diberikan.

Anda akan juga butuh mendaftarkan model pengguna penyesuaian anda dengan admin. Jika model pengguna penyesuaian anda memperpanjang django.contrib.auth.models.AbstractUser, anda dapat menggunakan kelas django.contrib.auth.admin.UserAdmin yang ada dari Django. Bagaimanapun, jika model pengguna anda memperpanjang AbstractBaseUser, anda akan butuh menentukan kelas ModelAdmin penyesuaian. Itu memungkinkan untuk mensubkelaskan awalan django.contrib.auth.admin.UserAdmin; bagaimanapun, anda akan butuh menimpa tiap pengertian yang mengacu ke bidang pada django.contrib.auth.models.AbstractUser yang tidak pada kelas pengguna penyesuaian anda.

Penyesuaian pengguna dan perizinan

Untuk membuatnya lebih mudah untuk menyertakan kerangka kerja perizinan Django kedalam kelas user anda sendiri, Django menyediakan PermissionsMixin. Ini adalah model abstrak anda dapat sertakan di susunan tingkat kelas untuk model user anda. memberikan anda semua metode dan bidang basisdata yang diperlukan untuk mendukung model perizinan Django.

PermissionsMixin menyediakan cara dan atribut berikut:

class models.PermissionsMixin
is_superuser

Boolean. Menunjuk bahwa pengguna ini mempunyai semua perizinan tanpa secara jelas menetapkan mereka.

get_group_permissions(obj=None)

Mengembalikan deretan karakter kumpulan perizinan yang pengguna punyai, melalui kelompok mreka.

Jika obj diloloskan, hanya mengembalikan perizinan kelompok untuk obyek tertentu ini.

get_all_permissions(obj=None)

Mengembalikan sekumpulan deretan karakter perizinan yang pengguna punyai, kedua melalui perizinan kelompok dan pengguna.

Jika obj diloloskan. hanya mengembalikan perizinan untuk obyek tertentu ini.

has_perm(perm, obj=None)

Mengembalikan True jika pengguna mempunyai perizinan tertentu, dimana perm dalam bentuk "<app label>.<permission codename>" (lihat permissions). Jika pengguna tidak aktif, metode ini akan selalu mengembalikan False.

Jika obj diloloskan, metode ini tidak akan memeriksa untuk sebuah perizinan untuk model, tetapi untuk obyek tertentu ini.

has_perms(perm_list, obj=None)

Mengembalikan True jika pengguna mempunyai setiap perizinan tertentu, dimana setiap perizinan dalam bentuk "<app label>.<permission codename>". Jika pengguna tidak aktif, metode ini akan selalu mengembalikan False.

Jika obj diloloskan, metode ini tidak akan memeriksa untuk perizinan-perizinan untuk model, tetapi untuk obyek tertentu.

has_module_perms(package_name)

Mengembalikan True jika pengguna mempunyai perizinan apapun di paket yang diberikan (label aplikasi Django). Jika pengguna tidak aktif, cara ini akan selalu mengembalikan False.

PermissionsMixin dan ModelBackend

Jika anda tidak menyertakan PermissionsMixin, anda harus memastikan anda tidak meminta metode perizinan pada ModelBackend. ModelBackend menggangap bahwa bidang tertentu itu tersedia di model user anda. Jika model user anda tidak menyediakan bidang tersebut, anda akan menerima kesalahan basisdata ketika anda memeriksa perizinan.

Penyesuaian pengguna dan model proxy

Satu batasan dari penyesuaian model user adalah bahwa memasang penyesuaian model user akan memutus tiap model proxy memperpanjang User. Model proxy harus berdasarkan pada kelas dasar nyata; dengan menentukan penyesuaian model user, anda memindah kemampuan dari Django untuk menciri yang handal kelas dasar.

Jika proyek anda menggunakan model proxy, anda harus salah satu merubah proxy untuk memperpanjang model yser yang digunakan di proyek anda, atau menggabungkan kebiasaan proxy anda kedalam subkelas User.

Sebuah contoh penuh

Ini adalah sebuah contoh dari admin-compliant aplikasi pengguna penyesuaian. Model pengguna ini menggunakan sebuah alamat surel sebagai nama pengguna, dan mempunyai tanggal lahir wajib; itu tidak menyediakan pemeriksaan perizinan, diluar bendera admin sederhana pada akun pengguna. Modl ini akan cocok dengan semua formulir otentifikasi pasang-tetap, kecuali untuk formulir pembuatan pengguna. Contoh ini menggambarkan bagaimana kebanyakan komponen bekerja bersama-sama, tetapi tidak cenderung menyalin secara langsung kedalam proyej untuk penggunaan produksi.

Kode ini akan semua tinggal di berkas models.py untuk aplikasi otentifikasi penyesuaian:

from django.db import models
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
)


class MyUserManager(BaseUserManager):
    def create_user(self, email, date_of_birth, password=None):
        """
        Creates and saves a User with the given email, date of
        birth and password.
        """
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=self.normalize_email(email),
            date_of_birth=date_of_birth,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, date_of_birth, password):
        """
        Creates and saves a superuser with the given email, date of
        birth and password.
        """
        user = self.create_user(
            email,
            password=password,
            date_of_birth=date_of_birth,
        )
        user.is_admin = True
        user.save(using=self._db)
        return user


class MyUser(AbstractBaseUser):
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    date_of_birth = models.DateField()
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = MyUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['date_of_birth']

    def get_full_name(self):
        # The user is identified by their email address
        return self.email

    def get_short_name(self):
        # The user is identified by their email address
        return self.email

    def __str__(self):              # __unicode__ on Python 2
        return self.email

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self):
        "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin

Kemudian, untuk mendaftar model pengguna penyesuaian dengan admin Django, kode berikut akan diwajibkan di berkas admin.py aplikasi:

from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField

from customauth.models import MyUser


class UserCreationForm(forms.ModelForm):
    """A form for creating new users. Includes all the required
    fields, plus a repeated password."""
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)

    class Meta:
        model = MyUser
        fields = ('email', 'date_of_birth')

    def clean_password2(self):
        # Check that the two password entries match
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super(UserCreationForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user


class UserChangeForm(forms.ModelForm):
    """A form for updating users. Includes all the fields on
    the user, but replaces the password field with admin's
    password hash display field.
    """
    password = ReadOnlyPasswordHashField()

    class Meta:
        model = MyUser
        fields = ('email', 'password', 'date_of_birth', 'is_active', 'is_admin')

    def clean_password(self):
        # Regardless of what the user provides, return the initial value.
        # This is done here, rather than on the field, because the
        # field does not have access to the initial value
        return self.initial["password"]


class UserAdmin(BaseUserAdmin):
    # The forms to add and change user instances
    form = UserChangeForm
    add_form = UserCreationForm

    # The fields to be used in displaying the User model.
    # These override the definitions on the base UserAdmin
    # that reference specific fields on auth.User.
    list_display = ('email', 'date_of_birth', 'is_admin')
    list_filter = ('is_admin',)
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Personal info', {'fields': ('date_of_birth',)}),
        ('Permissions', {'fields': ('is_admin',)}),
    )
    # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
    # overrides get_fieldsets to use this attribute when creating a user.
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'date_of_birth', 'password1', 'password2')}
        ),
    )
    search_fields = ('email',)
    ordering = ('email',)
    filter_horizontal = ()

# Now register the new UserAdmin...
admin.site.register(MyUser, UserAdmin)
# ... and, since we're not using Django's built-in permissions,
# unregister the Group model from admin.
admin.site.unregister(Group)

Akhirnya, tentukan model penyesuaian sebagai model pengguna awal untuk proyek anda menggunakan pengaturan AUTH_USER_MODEL di settings.py anda:

AUTH_USER_MODEL = 'customauth.MyUser'