主机管理+堡垒机系统开发:自定义用户认证(三)

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类就不会会没有以下的的权限

 

相关文章
相关标签/搜索