主機管理+堡壘機系統開發:自定義用戶認證(三)

1、開發目標

一、引子

class UserProfile(models.Model):
    """堡壘機的帳戶"""
    user = models.OneToOneField(User)
    name = models.CharField(max_length=64)
    bind_hosts = models.ManyToManyField("BindHost",blank=True)
    host_groups = models.ManyToManyField(HostGroup)
     
    def __str__(self):
        return self.name

真正你在生產中不是這這麼玩的,要徹底自定製
自定製就是把class User(AbstractUser)這個表重寫了,把他去掉之直接繼承下面的html

class AbstractUser(AbstractBaseUser, PermissionsMixin):

二、class AbstractUser表的的字段都在哪裏 

一、AbstractBaseUser類代碼

class AbstractUser(AbstractBaseUser, PermissionsMixin):
    """
    An abstract base class implementing a fully featured User model with
    admin-compliant permissions.

    Username, password and email are required. Other fields are optional.
    """
    username = models.CharField(_('username'), max_length=30, unique=True,
        help_text=_('Required. 30 characters or fewer. Letters, digits and '
                    '@/./+/-/_ only.'),
        validators=[
            validators.RegexValidator(r'^[\w.@+-]+$',
                                      _('Enter a valid username. '
                                        'This value may contain only letters, numbers '
                                        'and @/./+/-/_ characters.'), 'invalid'),
        ],
        error_messages={
            'unique': _("A user with that username already exists."),
        })
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=30, blank=True)
    email = models.EmailField(_('email address'), blank=True)
    is_staff = models.BooleanField(_('staff status'), default=False,
        help_text=_('Designates whether the user can log into this admin '
                    'site.'))
    is_active = models.BooleanField(_('active'), default=True,
        help_text=_('Designates whether this user should be treated as '
                    'active. Unselect this instead of deleting accounts.'))
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

    objects = UserManager()

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']

二、後臺web截圖

三、PermissionsMixin類代碼

class PermissionsMixin(models.Model):
    """
    A mixin class that adds the fields and methods necessary to support
    Django's Group and Permission model using the ModelBackend.
    """
    is_superuser = models.BooleanField(_('superuser status'), default=False,
        help_text=_('Designates that this user has all permissions without '
                    'explicitly assigning them.'))
    groups = models.ManyToManyField(Group, verbose_name=_('groups'),
        blank=True, help_text=_('The groups this user belongs to. A user will '
                                'get all permissions granted to each of '
                                'their groups.'),
        related_name="user_set", related_query_name="user")
    user_permissions = models.ManyToManyField(Permission,
        verbose_name=_('user permissions'), blank=True,
        help_text=_('Specific permissions for this user.'),
        related_name="user_set", related_query_name="user")

    class Meta:
        abstract = True

四、截圖

2、Specifying a custom User model(指定自定義用戶模型)

一、自定義參考官方說明

https://docs.djangoproject.com/en/2.1/topics/auth/customizing/python

https://www.cnblogs.com/ccorz/p/Django-zi-ding-yi-yong-hu-ren-zheng-xi-tong-zhi-zi.htmlgit

 

使用Django自定義用戶模型必須知足:web

  1. 模型必須有一個惟一的字段,可用於識別目的。數據庫

  2. 用戶給定名稱爲「短」的標識,用戶的全名爲「長」標識符。他們能夠返回徹底相同的值。django

 

     構建一個符合用戶自定義模型的最簡單的方法是繼承abstractbaseuser類。abstractbaseuser提供一個用戶模型的核心實現,包括密碼和符號密碼重置。Django自帶用用戶認證User也是繼承了它。一些關鍵的實現細節:後端

class models.CustomUserless

USERNAME_FIELD
ide

二、必須有一個惟一標識--USERNAME_FIELD

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

REQUIRED_FIELDSui

三、建立superuser時的必須字段

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

abstractbaseuser提供的方法

is_active(),is_authenticated()......

四、自定義models

class UserProfile(AbstractBaseUser,PermissionsMixin):
"""堡壘機的帳戶"""

    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    name = models.CharField(max_length=64)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)
    is_staff = models.BooleanField(
        ('staff status'),
        default=False,
        help_text=('Designates whether the user can log into this admin site.'),
    )

    bind_hosts = models.ManyToManyField("BindHost",blank=True)
    host_groups = models.ManyToManyField("HostGroup",blank=True)

    objects = UserProfileManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['name',]

五、settings中添加models文件名

AUTH_USER_MODEL = 'customauth.MyUser'

Django會去models中找這個類,因此要在原生的models.py中導入這個類。

3、代碼實現

一、models.py

class UserProfile(AbstractBaseUser,PermissionsMixin):
"""堡壘機的帳戶"""

    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    name = models.CharField(max_length=64)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)
    is_staff = models.BooleanField(
        ('staff status'),
        default=False,
        help_text=('Designates whether the user can log into this admin site.'),
    )

    bind_hosts = models.ManyToManyField("BindHost",blank=True)
    host_groups = models.ManyToManyField("HostGroup",blank=True)

    objects = UserProfileManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['name',]

二、settings.py

雖然你自定定義了表結構,可是你沒有明確的告訴django請用我用我自定的表結構,怎麼告訴它?

AUTH_USER_MODEL = 'web.UserProfile'

三、admin.py  

from asset import models
admin.site.register(models.UserProfile)

4、後臺效果

一、初始化數據庫,登陸後臺。此時密碼是明文顯示,若是想改密碼怎麼辦?

你指能改本身的,改不了別人的,那要該如何實現了 ?

這時,須要自定義admin顯示(官方都提供了)。你i自定義了認證,整個admin你都要本身徹底自定義

admin.py代碼

from django.contrib import admin

from web import models
# Register your models here.


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 web.models import UserProfile


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 = UserProfile
        fields = ('email', 'name')

    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 = UserProfile
        fields = ('email', 'password', 'name', '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 UserProfileAdmin(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', 'name','is_staff', 'is_admin')
    list_filter = ('is_admin','is_staff')
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Personal info', {'fields': ('name',)}),
        ('堡壘機主機受權', {'fields': ('bind_hosts','host_groups')}),
        ('Permissions', {'fields': ('is_admin','is_staff','user_permissions','groups')}),
    )
    # 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', 'name', 'password1', 'password2')}
        ),
    )
    search_fields = ('email',)
    ordering = ('email',)
    filter_horizontal = ('user_permissions','groups','bind_hosts','host_groups')

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



class RemoteUserAdmin(admin.ModelAdmin):
    list_display = ('username','auth_type','password')


admin.site.register(models.Host)
admin.site.register(models.HostGroup)
admin.site.register(models.BindHost)
admin.site.register(models.RemoteUser,RemoteUserAdmin)
admin.site.register(models.IDC)
admin.site.register(models.Session)

二、fieldsets 是什麼意思?

後端代碼 :

    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Personal info', {'fields': ('name',)}),
        ('Permissions', {'fields': ('is_admin','is_staff','user_permissions','groups')}),
    )

後臺截圖:

是否是加了個藍線,是爲了美化好區分

三、add_fieldsets是什麼?

代碼

    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'name', 'password1', 'password2')}
        ),

截圖

是否是必須填寫的字段呀 

四、定義完表結構註冊完後,登錄發現登陸界面是輸入email

  

五、爲何登陸不了?設置紅框的就能夠了

        

六、編輯用戶:

七、更改密碼:沒有Group:​

    

 

八、若是沒有繼承PermissionsMixin類就不會會沒有以下的的權限

 

相關文章
相關標籤/搜索