Django内置的认证系统
选择使用django默认使用的db.sqlite
1.下载驱动
2.点击files选框的...按钮那里,选择对应项目根目录下的db.sqlite
3.Python3 manage.py migrate
4.Python3 manage.py createsuperuser,就可以在命令行创建一个超级用户的账户
导入auth模块
from django.contrib import auth
方法(部分)
authenticate()
这是用于验证用户名以及密码是否正确,一般需要username password两个关键字参数
如果验证通过,会返回一个 User 对象。authenticate()会在User 对象上设置一个属性来标识后端已经认证了该用户,且该信息在后续的登录过程中是需要的。
用法:user = authenticate(username='user',password='password')
当我们试图登陆一个从数据库中直接取出来不经过authenticate()的User对象时会报错!!!
login(request, user)
该函数接受一个HttpRequest对象,以及一个认证了的User对象.此函数使用django的session框架给某个已认证的用户附加上session id等信息。
1 from django.contrib.auth import authenticate, login 2 3 4 def my_view(request): 5 6 username = request.POST['username'] 7 8 password = request.POST['password'] 9 10 user = authenticate(username=username, password=password) 11 12 if user is not None: 13 14 login(request, user) 15 16 # Redirect to a success page. 17 18 ... 19 20 else: 21 22 # Return an 'invalid login' error message. 23 24 ...
logout(request) 注销用户
from django.contrib.auth import logout def logout(request): auth.logout(request) return redirect("/login/")
该函数接受一个HttpRequest对象,无返回值。当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。
is_authenticated()
用于判断当前请求是否通过了认证
def my_view(request): if not request.user.is_authenticated(): return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
login_requierd()
用于快捷地给某个视图添加登录校验
from django.contrib.auth.decorators import login_required @login_required def my_view(request): ...
若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' (这个值可以在settings.py文件中通过LOGIN_URL进行修改)。
# 设置这个网站默认登录的页面
LOGIN_URL = "/login/"
并传递当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。
User对象
User 对象属性:username, password(必填项)password用哈希算法保存到数据库
is_staff : 用户是否拥有网站的管理权限.
is_active : 是否允许用户登录, 设置为``False``,可以不用删除用户来禁止 用户登录
is_authenticated()如果是真正的 User 对象,返回值恒为 True 。 用于检查用户是否已经通过了认证。通过认证并不意味着用户拥有任何权限,这个方法甚至也不检查该用户是否处于激活状态,只是表明用户成功的通过了认证。
创建用户
使用 create_user() 辅助函数创建用户:
from django.contrib.auth.models import User user = User.objects.create_user(username='用户名',password='密码',email='邮件地址')
check_password(passwd)
用户需要修改密码的时候,首先要让其输入原来的密码 ,如果给定的值通过了密码检查,返回 True
ok = user.check_password('密码')
set_password()
用于修改密码
user = User.objects.get(username='用户名') user.set_password(password='设置的密码') user.save()
设置完密码后,一定要调用用户对象的save方法保存修改后的
1 @login_required 2 def set_password(request): 3 user = request.user 4 err_msg = '' 5 if request.method == 'POST': 6 old_password = request.POST.get('old_password', '') 7 new_password = request.POST.get('new_password', '') 8 repeat_password = request.POST.get('repeat_password', '') 9 # 检查旧密码是否正确 10 if user.check_password(old_password): 11 if not new_password: 12 err_msg = '新密码不能为空' 13 elif new_password != repeat_password: 14 err_msg = '两次密码不一致' 15 else: 16 user.set_password(new_password) 17 user.save() 18 return redirect("/login/") 19 else: 20 err_msg = '原密码输入错误' 21 content = { 22 'err_msg': err_msg, 23 } 24 return render(request, 'set_password.html', content) 25 26
扩展auth_user表
继承内置的auth_user表的对应的类,来定义一个自己的ORM类。
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表来做用户认证。写法如下:
# 引用Django自带的User表,继承使用时需要设置 AUTH_USER_MODEL = "app名.UserInfo"
将Django的form组件和认证放在一起的小栗子:
1 from django.shortcuts import render, redirect, HttpResponse 2 from django.contrib import auth 3 from django.contrib.auth.models import User 4 from django.contrib.auth.decorators import login_required 5 from about_auth import froms 6 7 8 # Create your views here. 9 def login(request): 10 if request.method == 'POST': 11 form_obj = froms.LoginForm(request.POST) 12 if form_obj.is_valid(): 13 dic = form_obj.cleaned_data 14 # 验证用户名和密码是否正确 15 user = auth.authenticate(username=dic["username"], password=dic["password"]) 16 if user: 17 # 调用内置的login方法 18 # 1.生成session数据,把session写入cookie 19 # 后来每次进来的时候,request.user拿到当前值 20 auth.login(request, user) 21 return redirect('/home/') 22 else: 23 print(form_obj) 24 return render(request,'login.html',{'form_obj':form_obj, }) 25 form_obj = froms.LoginForm() 26 return render(request, 'login.html', {'form_obj': form_obj}) 27 28 29 def register(request): 30 if request.method == 'POST': 31 form_obj = froms.RegForm(request.POST) 32 if form_obj.is_valid(): 33 # 创建普通用户的专用方法 34 User.objects.create_user(username=form_obj.cleaned_data["username"], 35 password=form_obj.cleaned_data["password"]) 36 return redirect("/login/") 37 else: 38 return render(request, 'register.html', {'form_obj': form_obj}) 39 form_obj = froms.RegForm() 40 return render(request, 'register.html', {'form_obj': form_obj}) 41 42 43 @login_required 44 def home(request): 45 return render(request, 'home.html') 46 47 48 @login_required 49 def set_pwd(request): 50 if request.method == 'POST': 51 form_obj = froms.SetPwdForm(request.POST) 52 if form_obj.is_valid(): 53 dic = form_obj.cleaned_data 54 # 先校验原密码对不对 55 user_obj = request.user 56 if user_obj.check_password(dic["old_pwd"]): 57 if dic["new_pwd"] == dic["con_pwd"]: 58 # 修改原密码 59 user_obj.set_password(dic["new_pwd"]) 60 user_obj.save() 61 return redirect('/login/') 62 else: 63 return HttpResponse("原密码错误") 64 form_obj = froms.SetPwdForm() 65 return render(request, 'set_pwd.html', {'form_obj': form_obj, }) 66 67 68 def logout(request): 69 auth.logout(request) 70 return redirect("/login/")
1 from django import forms 2 3 4 class RegForm(forms.Form): 5 username = forms.CharField( 6 min_length=3, 7 label='用户名', 8 error_messages={ 9 'required': '用户名不能为空', 10 'min_length': '用户名最少不能少于三个字符', 11 }, 12 widget=forms.widgets.TextInput(attrs={'class': 'form-control', }) 13 ) 14 password = forms.CharField( 15 min_length=6, 16 label='密码', 17 error_messages={ 18 'required': '密码不能为空', 19 'min_length': '密码不能少于6位数', 20 }, 21 widget=forms.widgets.PasswordInput(attrs={'class': 'form-control', }) 22 ) 23 con_pwd = forms.CharField( 24 min_length=6, 25 label='确认密码', 26 error_messages={ 27 'required': '密码不能为空', 28 'min_length': '密码不能少于6位数', 29 }, 30 widget=forms.widgets.PasswordInput(attrs={'class': 'form-control', }) 31 ) 32 33 34 class LoginForm(forms.Form): 35 username = forms.CharField( 36 min_length=3, 37 label='用户名', 38 error_messages={ 39 'required': '用户名不能为空', 40 'min_length': '用户名最少不能少于三个字符', 41 }, 42 widget=forms.widgets.TextInput(attrs={'class': 'form-control', }) 43 ) 44 password = forms.CharField( 45 min_length=6, 46 label='密码', 47 error_messages={ 48 'required': '密码不能为空', 49 'min_length': '密码不能少于6位数', 50 }, 51 widget=forms.widgets.PasswordInput(attrs={'class': 'form-control', }) 52 ) 53 54 55 class SetPwdForm(forms.Form): 56 old_pwd = forms.CharField( 57 min_length=6, 58 label='原密码', 59 error_messages={ 60 'required': '密码不能为空', 61 'min_length': '密码不能少于6位数', 62 }, 63 widget=forms.widgets.PasswordInput(attrs={'class': 'form-control', }) 64 ) 65 new_pwd = forms.CharField( 66 min_length=6, 67 label='新密码', 68 error_messages={ 69 'required': '密码不能为空', 70 'min_length': '密码不能少于6位数', 71 }, 72 widget=forms.widgets.PasswordInput(attrs={'class': 'form-control', }) 73 ) 74 con_pwd = forms.CharField( 75 min_length=6, 76 label='确认密码', 77 error_messages={ 78 'required': '密码不能为空', 79 'min_length': '密码不能少于6位数', 80 }, 81 widget=forms.widgets.PasswordInput(attrs={'class': 'form-control', }) 82 )
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1"> 6 <title>注册</title> 7 <link rel="stylesheet" href="../static/bootstrap-3.3.7/css/bootstrap.min.css"> 8 <style type="text/css"> 9 .top{ 10 margin-top: 5%; 11 } 12 </style> 13 </head> 14 <body> 15 <div class="container-fluid"> 16 <div class="row"> 17 <div class="top col-md-4 col-md-offset-4"> 18 <div class="panel panel-danger"> 19 <div class="panel-heading"> 20 <h3 class="panel-title"><strong>欢迎注册</strong></h3> 21 </div> 22 <div class="panel-body"> 23 <form action="" method="post" novalidate autocomplete="off"> 24 {% csrf_token %} 25 <div class="form-group"> 26 <label for="{{ form_obj.username.id_for_label }}">{{ form_obj.username.label }}</label> 27 {{ form_obj.username }} 28 <span class="help-block">{{ form_obj.username.errors.0 }}</span> 29 </div> 30 <div class="form-group"> 31 <label for="{{ form_obj.password.id_for_label }}">{{ form_obj.password.label }}</label> 32 {{ form_obj.password }} 33 <span class="help-block">{{ form_obj.password.errors.0 }}</span> 34 </div> 35 <div class="form-group"> 36 <label for="{{ form_obj.con_pwd.id_for_label }}">{{ form_obj.con_pwd.label }}</label> 37 {{ form_obj.con_pwd }} 38 <span class="help-block">{{ form_obj.con_pwd.errors.0 }}</span> 39 </div> 40 <button type="submit" class="btn btn-default btn-block">注册</button> 41 </form> 42 </div> 43 </div> 44 </div> 45 </div> 46 </div> 47 </body> 48 </html>
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1"> 6 <title>登录</title> 7 <link rel="stylesheet" href="../static/bootstrap-3.3.7/css/bootstrap.min.css"> 8 <style type="text/css"> 9 .top{ 10 margin-top: 5%; 11 } 12 </style> 13 </head> 14 <body> 15 <div class="container-fluid"> 16 <div class="row"> 17 <div class="top col-md-4 col-md-offset-4"> 18 <div class="panel panel-primary"> 19 <div class="panel-heading"> 20 <h3 class="panel-title"><strong>欢迎登录</strong></h3> 21 </div> 22 <div class="panel-body"> 23 <form action="" method="post" novalidate autocomplete="off"> 24 {% csrf_token %} 25 <div class="form-group"> 26 <label for="{{ form_obj.username.id_for_label }}">{{ form_obj.username.label }}</label> 27 {{ form_obj.username }} 28 <span class="help-block">{{ form_obj.username.errors.0 }}</span> 29 </div> 30 <div class="form-group"> 31 <label for="{{ form_obj.password.id_for_label }}">{{ form_obj.password.label }}</label> 32 {{ form_obj.password }} 33 <span class="help-block">{{ form_obj.password.errors.0 }}</span> 34 </div> 35 <button type="submit" class="btn btn-default btn-block">登录</button> 36 </form> 37 </div> 38 </div> 39 </div> 40 </div> 41 </div> 42 </body> 43 </html>
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1"> 6 <title>home</title> 7 8 </head> 9 <body> 10 <h1>你好,用户{{ request.user.username }}</h1> 11 <a href="/logout/">注销</a> 12 <a href="/set_pwd/">修改密码</a> 13 </body> 14 </html>
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1"> 6 <title>重置密码</title> 7 <link rel="stylesheet" href="../static/bootstrap-3.3.7/css/bootstrap.min.css"> 8 <style type="text/css"> 9 .top{ 10 margin-top: 5%; 11 } 12 </style> 13 </head> 14 <body> 15 <div class="container-fluid"> 16 <div class="row"> 17 <div class="top col-md-4 col-md-offset-4"> 18 <div class="panel panel-danger"> 19 <div class="panel-heading"> 20 <h3 class="panel-title"><strong>重置密码</strong></h3> 21 </div> 22 <div class="panel-body"> 23 <form action="" method="post" novalidate autocomplete="off"> 24 {% csrf_token %} 25 <div class="form-group"> 26 <label for="{{ form_obj.old_pwd.id_for_label }}">{{ form_obj.old_pwd.label }}</label> 27 {{ form_obj.old_pwd }} 28 <span class="help-block">{{ form_obj.old_pwd.errors.0 }}</span> 29 </div> 30 <div class="form-group"> 31 <label for="{{ form_obj.new_pwd.id_for_label }}">{{ form_obj.new_pwd.label }}</label> 32 {{ form_obj.new_pwd }} 33 <span class="help-block">{{ form_obj.new_pwd.errors.0 }}</span> 34 </div> 35 <div class="form-group"> 36 <label for="{{ form_obj.con_pwd.id_for_label }}">{{ form_obj.con_pwd.label }}</label> 37 {{ form_obj.con_pwd }} 38 <span class="help-block">{{ form_obj.con_pwd.errors.0 }}</span> 39 </div> 40 <button type="submit" class="btn btn-default btn-block">确认</button> 41 </form> 42 </div> 43 </div> 44 </div> 45 </div> 46 </div> 47 </body> 48 </html>