- 什么是Auth模块
- auth模块用法
- Auth模块功能详解
- 扩展默认的auth_user表
-曾老湿, 江湖人称曾老大。
-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。
什么是Auth模块
介绍 |
---|
Auth模块是Django自带的用户认证模块:
我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,这还真是个麻烦的事情呢。
Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点。它内置了强大的用户认证系统--auth,它默认使用 auth_user 表来存储用户数据。
auth模块用法
创建项目 |
---|

数据库迁移
代码语言:javascript复制MacBook-pro:auth_module driverzeng$ python3 manage.py makemigrations
MacBook-pro:auth_module driverzeng$ python3 manage.py migrate

这个表里的用户,不能直接往里面写,得使用命令,还是运行manage.py
代码语言:javascript复制# 创建超级用户
MacBook-pro:auth_module driverzeng$ python3 manage.py createsuperuser


模板层 |
---|
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
<div>
<lable>用户:<input type="text" name="name"></lable>
</div>
<div>
<lable>密码:<input type="text" name="pwd"></lable>
</div>
<input type="submit" value="登录">
</form>
</body>
</html>
视图层 |
---|
from django.shortcuts import render,HttpResponse,redirect
# Create your views here.
from django.contrib import auth
def login(request):
if request.method == 'GET':
return render(request,'login.html')
elif request.method == 'POST':
name = request.POST.get('name')
pwd = request.POST.get('pwd')
user = auth.authenticate(request,username=name,password=pwd)
## 相当于:user = models.User.objects.filter(name=name,pwd=pwd).first()
if user:
return HttpResponse('登录成功')
else:
return HttpResponse('用户名或密码错误')
路由层 |
---|
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login),
]


Auth模块功能详解
登录 |
---|
from django.shortcuts import render,HttpResponse,redirect
# Create your views here.
from django.contrib import auth
def login(request):
if request.method == 'GET':
return render(request,'login.html')
elif request.method == 'POST':
name = request.POST.get('name')
pwd = request.POST.get('pwd')
user = auth.authenticate(request,username=name,password=pwd)
## 相当于:user = models.User.objects.filter(name=name,pwd=pwd).first()
if user:
# 登录,其实就是把用户的信息放到session中
auth.login(request,user)
## 之前是这样 request.session['name'] = name
return HttpResponse('登录成功')
else:
return HttpResponse('用户名或密码错误')


取出当前登陆用户 |
---|
只要登录成功,之后在任意视图,都可以取出该用户,这个功能太强大了,省了我们很多事
代码语言:javascript复制def test(request):
user=request.user
print(user)
return HttpResponse('当前登录的用户:%s' % user)
代码语言:javascript复制from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login),
url(r'^test/', views.test),
]


如果没有登录就会是一个匿名用户:AnonymousUser


注销 |
---|
def user_logout(request):
auth.logout(request)
user = request.user
return HttpResponse('注销 [%s] 成功' %user)
代码语言:javascript复制from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login),
url(r'^test/', views.test),
url(r'^user_logout/', views.user_logout),
]



登录认证装饰器 |
---|
目前 我有个test页面,不管用户有没有登录都可以访问,因为没有登录的时候,可以用匿名用户访问,Django内置了一个登录认证的装饰器,如果没有登录,或者是匿名用户,可以跳转到指定的页面
模板层
代码语言:javascript复制<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="UTF-8">
<title>个人中心</title>
</head>
<body>
当前登录用户:{{ user }}
<div>
<a href="/user_logout/">点我注销</a>
</div>
</body>
</html>
视图层
代码语言:javascript复制from django.shortcuts import render, HttpResponse, redirect
from django.contrib.auth.decorators import login_required
# Create your views here.
from django.contrib import auth
def login(request):
if request.method == 'GET':
return render(request, 'login.html')
elif request.method == 'POST':
name = request.POST.get('name')
pwd = request.POST.get('pwd')
user = auth.authenticate(request, username=name, password=pwd)
## 相当于:user = models.User.objects.filter(name=name,pwd=pwd).first()
if user:
# 登录,其实就是把用户的信息放到session中
auth.login(request, user)
## 之前是这样 request.session['name'] = name
return redirect('test')
else:
return HttpResponse('用户名或密码错误')
@login_required(redirect_field_name='zls', login_url='/login/')
def test(request):
user = request.user
print(user)
return render(request,'test.html',locals())
def user_logout(request):
user = request.user
auth.logout(request)
return redirect('/login/')
路由层
代码语言:javascript复制from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login),
url(r'^test/', views.test),
url(r'^user_logout/', views.user_logout),
]



代码语言:javascript复制## 导入装饰器:from django.contrib.auth.decorators import login_required
## redirect_field_name 修改url的?后面传递的参数
## login_url 如果没有登录,跳转到页面
但是如果装饰器需要传递参数,如果有一万个视图函数,我就要传递一万次参数?很麻烦,所以Django帮我们做了一件事,settings文件中,修改即可。
代码语言:javascript复制LOGIN_URL = '/login/'
代码语言:javascript复制from django.shortcuts import render, HttpResponse, redirect
from django.contrib.auth.decorators import login_required
# Create your views here.
from django.contrib import auth
def login(request):
if request.method == 'GET':
return render(request, 'login.html')
elif request.method == 'POST':
name = request.POST.get('name')
pwd = request.POST.get('pwd')
user = auth.authenticate(request, username=name, password=pwd)
## 相当于:user = models.User.objects.filter(name=name,pwd=pwd).first()
if user:
# 登录,其实就是把用户的信息放到session中
auth.login(request, user)
## 之前是这样 request.session['name'] = name
return redirect('/test/')
else:
return HttpResponse('用户名或密码错误')
@login_required()
def test(request):
user = request.user
print(user)
return render(request,'test.html',locals())
def user_logout(request):
user = request.user
auth.logout(request)
return redirect('/login/')
用户注册 |
---|
from django.shortcuts import render, HttpResponse, redirect
from django.contrib.auth.decorators import login_required
# Create your views here.
from django.contrib import auth
def login(request):
if request.method == 'GET':
return render(request, 'login.html')
elif request.method == 'POST':
name = request.POST.get('name')
pwd = request.POST.get('pwd')
user = auth.authenticate(request, username=name, password=pwd)
## 相当于:user = models.User.objects.filter(name=name,pwd=pwd).first()
if user:
# 登录,其实就是把用户的信息放到session中
auth.login(request, user)
## 之前是这样 request.session['name'] = name
return redirect('/test/')
else:
return HttpResponse('用户名或密码错误')
@login_required()
def test(request):
user = request.user
print(user)
return render(request,'test.html',locals())
def user_logout(request):
user = request.user
auth.logout(request)
return redirect('/login/')
from django.contrib.auth.models import User
def register(request):
name='cls'
pwd='123'
## 不能这么创建:密码不能是明文的
## user = User.objects.create(username=name,password=pwd)
## 创建超级用户
#user = User.objects.create_superuser(username=name,password=pwd)
## 创建普通用户
user = User.objects.create_user(username=name,password=pwd)
return HttpResponse('用户:%s 注册成功' %user)
代码语言:javascript复制from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login),
url(r'^test/', views.test),
url(r'^user_logout/', views.user_logout),
url(r'^register/', views.register),
]


校验密码 |
---|
因为密码是加密的,所以我们不能直接拿出来,还得用Django给我们写的方法。
代码语言:javascript复制def check_pwd(request):
pwd = '123'
res = request.user.check_password(pwd)
print(res)
if res:
return HttpResponse('密码校验成功')
else:
return HttpResponse('密码校验失败')
代码语言:javascript复制from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login),
url(r'^test/', views.test),
url(r'^user_logout/', views.user_logout),
url(r'^register/', views.register),
url(r'^check_pwd/', views.check_pwd),
]

zls
用户的密码是:zls12345
def check_pwd(request):
pwd = 'zls12345'
res = request.user.check_password(pwd)
print(res)
if res:
return HttpResponse('密码校验成功')
else:
return HttpResponse('密码校验失败')


修改密码 |
---|
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login),
url(r'^test/', views.test),
url(r'^user_logout/', views.user_logout),
url(r'^register/', views.register),
url(r'^check_pwd/', views.check_pwd),
url(r'^set_pwd/', views.set_pwd),
]
代码语言:javascript复制def set_pwd(request):
pwd = 'zls111'
user = request.user
user.set_password(pwd)
user.save()
return HttpResponse('OK')



注意:修改密码一定要 调用save方法,否则不保存。
是否认证通过 |
---|
def auth_1(request):
res = request.user.is_authenticated
print(res)
if res:
return HttpResponse('认证成功')
else:
return HttpResponse('认证失败')
代码语言:javascript复制from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login),
url(r'^test/', views.test),
url(r'^user_logout/', views.user_logout),
url(r'^register/', views.register),
url(r'^check_pwd/', views.check_pwd),
url(r'^set_pwd/', views.set_pwd),
url(r'^auth_1/', views.auth_1),
]


该方法,主要不是在视图使用,是在模板中使用。
封号和后台管理 |
---|
is_staff : 用户是否拥有网站的管理权限.
is_active : 是否允许用户登录, 设置为 False,可以在不删除用户的前提下禁止用户登录。
扩展默认的auth_user表
这内置的认证系统这么好用,但是auth_user表字段都是固定的那几个,我在项目中没法拿来直接使用啊!
比如,我想要加一个存储用户手机号的字段,怎么办?
聪明的你可能会想到新建另外一张表然后通过一对一和内置的auth_user表关联,这样虽然能满足要求但是有没有更好的实现方式呢?
答案是当然有了。
我们可以通过继承内置的 AbstractUser 类,来定义一个自己的Model类。
这样既能根据项目需求灵活的设计用户表,又能使用Django强大的认证系统了。
两种方式,复用User表
一对一关联auth_user表 |
---|
from django.db import models
# Create your models here.
from django.contrib.auth.models import User
class UserDetail(models.Model):
phone = models.CharField(max_length=32)
# 如果是从外部引入的表模型是不能加 引号的
#user = models.OneToOneField(to='User')
user = models.OneToOneField(to=User)
数据库迁移
代码语言:javascript复制MacBook-pro:~ driverzeng$ cd /Users/driverzeng/PycharmProjects/auth_module
MacBook-pro:auth_module driverzeng$ python3 manage.py makemigrations
MacBook-pro:auth_module driverzeng$ python3 manage.py migrate

定义表模型继承 |
---|
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
"""
用户信息表
"""
nid = models.AutoField(primary_key=True)
phone = models.CharField(max_length=11, null=True, unique=True)
def __str__(self):
return self.username
注意:
按上面的方式扩展了内置的auth_user表之后,一定要在settings.py中告诉Django,我现在使用我新定义的UserInfo表来做用户认证。写法如下:
代码语言:javascript复制# 引用Django自带的User表,继承使用时需要设置
AUTH_USER_MODEL = "app01.UserInfo"
再次注意:
一旦我们指定了新的认证系统所使用的表,我们就需要重新在数据库中创建该表,而不能继续使用原来默认的auth_user表了。