python认证系统_[Python自学] Django的认证系统

一、Django自带的用户认证

我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。

此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,这还真是个麻烦的事情呢。

Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点。

它内置了强大的用户认证系统--auth,它默认使用 auth_user 表来存储用户数据。

1.初始化数据库

执行初始化数据库:

python manage.py makemigrations

python manage.py migrate

可以看到,在数据库中django创建了一张叫做auth_user的表:

这张表就是用来供auth模块存放用户信息的表。

2.创建superuser

在命令行执行以下命令:

python manage.py createsuperuser

然后根据提示,创建用户名和密码,这里我们的用户名为"leo",密码为"leokale1234!"。

3.在数据库中查看创建好的superuser

在auth_user表中可以看到已经创建好的superuser:leo,密码是经过SHA256加密的。is_superuser表示leo用户是超级用户。

二、auth模块

1.导入auth模块:

from django.contrib import auth

2.使用authenticate()进行认证

该方法只是对用户名密码进行比对验证:

user_obj = auth.authenticate(username='leokale',password='leokale1234!')

使用authenticate()验证用户名以及密码是否正确,一般需要username 、password两个关键字参数。

如果认证成功,则返回一个User对象,并在User对象中设置一个标识该用户以被后端认证。

3.将认证后的用户对象封装到request中(auth.login()函数)

在login()视图函数中,使用auth中的login()函数:

deflogin(request):if request.method == "POST":

username= request.POST.get("username")

pwd= request.POST.get("password")

user_obj= auth.authenticate(username=username, password=pwd) #去后台数据库auth_user中验证

ifuser_obj:

auth.login(request, user_obj)#将登录的用户封装到request.user中

return redirect("/index/") #如果验证通过,则跳转到index页面

return render(request, "login.html") #如果是get请求,返回login页面

从此以后,用户的每次访问页面,django的中间件: django.contrib.auth.middleware.AuthenticationMiddleware,就会帮我们根据cookie中的session_id去session中找是否登录,如果已经登录,则将该用户信息封装到request.user中,我们就可以在其他页面对应的视图函数中获取了。这里的中间件帮我们统一做了查询session,获取session的操作。

4.从request中获取已登录的用户信息

在index()视图函数中获取已登录用户信息:

defindex(request):print(request.user.username) #获取已登录的username

return render(request, 'index.html')

如果用户未登录,request.user获取到的是一个匿名用户对象(AnonymousUser Object),request.user.username为None。

在request.user中,除了可以获取username,还可以获取很多用户相关的信息(auth_user表中的字段):

defindex(request):print(request.user.username)print(request.user.password) #密码的SHA256加密

print(request.user.is_superuser) #是否是超级用户

print(request.user.is_authenticated) #判断是否通过了认证

print(request.user.is_staff) #用户是否拥有网站的管理权限

print(request.user.is_active) #是否允许用户登录,设置为False,则禁止用户登录

return render(request, 'auth_index.html',{"username":request.user.username})

打印结果:

leo

pbkdf2_sha256$180000$JIPSlFr8GvYz$wfS6A2qiyDthNA2+tNIdER1TbSCfc4wTuokZA0s8kCE=True

True

True

True

5.用户注销

只需要在视图函数中调用auth.logout()即可清除session,实现注销:

auth.logout(request)

当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。

6.使用装饰器快捷的提供登录校验

auth模块为我们提供了一个装饰器工具,用来快捷的给某个视图添加登录校验。

from django.contrib.auth.decorators importlogin_required

@login_requireddefmy_view(request):

...

如果用户没有登录,则会跳转到django默认的URL'accounts/login',并传递当前访问URL的绝对路径。

如果要修改该默认的登录URL,则需要在setting中通过LOGIN_URL修改:

如果登录成功,则会跳转到请求的URL。

三、auth提供的其他一些功能

1.创建用户

from django.contrib.auth.models importUser

user= User.objects.create_user(username='用户名',password='密码',email='邮箱',...)

auth 提供的一个创建新用户的方法,需要提供必要参数(username、password)等。

2.创建超级用户

from django.contrib.auth.models importUser

user_obj= User.objects.create_superuser(username='用户名',password='密码',email='邮箱',...)

auth 提供的一个创建新的超级用户的方法,需要提供必要参数(username、password)等。

3.修改密码

用户登录验证通过后,获得了user_obj,调用以下代码修改密码:

user_obj.set_password('新密码')

user_obj.save()

注意,设置完密码,必须要调用用户对象的save方法。。

修改密码示例:

@login_requireddefset_password(request):

user=request.user

err_msg= ''

if request.method == 'POST':

old_password= request.POST.get('old_password', '')

new_password= request.POST.get('new_password', '')

repeat_password= request.POST.get('repeat_password', '')#检查旧密码是否正确

ifuser.check_password(old_password):if notnew_password:

err_msg= '新密码不能为空'

elif new_password !=repeat_password:

err_msg= '两次密码不一致'

else:

user.set_password(new_password)

user.save()return redirect("/login/")else:

err_msg= '原密码输入错误'content={'err_msg': err_msg,

}return render(request, 'set_password.html', content)

View Code

四、扩展默认的auth_user表

比如,我想要加一个存储用户手机号的字段,怎么办?

我们可能会想到新建另外一张表然后通过一对一和内置的auth_user表关联,这样虽然能满足要求但是有没有更好的实现方式呢?

答案是当然有了。

我们可以通过继承内置的 AbstractUser 类,来定义一个自己的Model类。然后将默认的auth_user(对应User类,from django.contrib.auth.models import User)表换成使用我们自己定义的表。

from django.contrib.auth.models importAbstractUserclassUserInfo(AbstractUser):"""用户信息表"""nid= models.AutoField(primary_key=True)

phone= models.CharField(max_length=11, null=True, unique=True)def __str__(self):return self.username

在创建UserInfo的时候,要继承AbstractUser。auth_user中的字段都在AbstractUser类中。

查看AbstractUser的源码:

classAbstractUser(AbstractBaseUser, PermissionsMixin):"""An abstract base class implementing a fully featured User model with

admin-compliant permissions.

Username and password are required. Other fields are optional."""username_validator=UnicodeUsernameValidator()

username=models.CharField(

_('username'),

max_length=150,

unique=True,

help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),

validators=[username_validator],

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=150, 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.'),

)

View Code

可以看到,AbstractUser类中定义了username、first_name、last_name、email、is_staff、is_active、date_joined等字段。并且继承于AbstractBaseUser和PermissionsMixin类。

查看AbstractBaseUser类:

classAbstractBaseUser(models.Model):

password= models.CharField(_('password'), max_length=128)

last_login= models.DateTimeField(_('last login'), blank=True, null=True)

......

View Code

可以看到,AbstractBaseUser类中定义了password和last_login字段。

再查看PermissionsMixin类:

classPermissionsMixin(models.Model):"""Add the fields and methods necessary to support the Group and Permission

models 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",

)

......

View Code

可以看到PermissionsMixin类中定义了is_superuser字段,以及groups、user_permissions等多表对应关系。

定义完model后,需要告诉Django,在setting中设置:

#引用Django自带的User表,继承使用时需要设置

AUTH_USER_MODEL = "app名.UserInfo"

自定义认证系统默认使用的数据表之后,我们就可以像使用默认的auth_user表那样使用我们的UserInfo表了。比如:

创建普通用户:

UserInfo.objects.create_user(username='用户名', password='密码')

创建超级用户:

UserInfo.objects.create_superuser(username='用户名', password='密码')

注意:

一旦我们指定了新的认证系统所使用的表,我们就需要重新在数据库中创建该表,而不能继续使用原来默认的auth_user表了。也就是说我们不能再使用User类来进行操作,而要使用我们的UserInfo类。

♛♛♛♛♛♛End♛♛♛♛♛♛

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值