组团学

高阶应用-用户验证

阅读 (263452)

一、说明

User是auth模块中维护用户信息的关系模式(继承了models.Model), 数据库中该表被命名为auth_user

二、User表的SQL描述

CREATE TABLE "auth_user" ( "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "password" varchar(128) NOT NULL, "last_login" datetime NULL, "is_superuser" bool NOT NULL, "first_name" varchar(30) NOT NULL, "last_name" varchar(30) NOT NULL, "email" varchar(254) NOT NULL, "is_staff" bool NOT NULL, "is_active" bool NOT NULL, "date_joined" datetime NOT NULL, "username" varchar(30) NOT NULL UNIQUE )

导入

from django.contrib.auth.models import User

三、用户模型属性方法

  • is_staff

    Boolean。决定用户是否可以访问admin管理界面。默认False

  • is_active

    Boolean。 用户是否活跃,默认True。一般不删除用户,而是将用户的is_active设为False

  • is_authenticated()

    用户是否通过验证,登陆

    request.user.is_authenticated() 可以判断当前用户是否登录

    登录则为 True 否则为False

  • make_password(password)

    给密码加密 django自带的加密功能是hash 加盐

  • check_password(password)

    检查用户输入的密码是否正确

  • set_password(password)

    修改用户密码

  • authenticate() 认证用户名和密码是否正确

    authenticate(username=username, password=password)

    使用

    from django.contrib.auth import authenticate
  • create_user() 创建用户

    使用系统User模型

    from django.contrib.auth.models import User User.objects.create_user(username, email, password)
  • request.user 获取当前登录用户对象

    request.user.username 获取当前登录用户的用户名

  • last_login 自动保存 不需要自己添加代码

    上一次的登录时间,为datetime对象,默认为当时的时间。

    user.last_login = timezone.now()

  • request.user.username

    获取当前登录用户的用户名

  • login_required 设置视图函数必须登录才允许访问

    from django.contrib.auth.decorators import login_required @login_required(login_url='/') # 没有登录则跳转到首页 def center(request): return Httpresponse('个人中心')
  • login 登录

  • logout 退出登录

四、注册

  • 模板 register.html

    <!DOCTYPE html> <html> <head> <title>注册页面</title> <style> .pg_header{ position: fixed; height: 48px; top: 0; left: 0; right: 0; background-color: #2459a2; line-height: 48px; } .pg_header .logo{ margin: 0 auto; float: left; width: 200px; text-align: center; line-height: 48px; font-size: 28px; color: white; } .pg_dl{ left: 400px; display: inline-block; padding: 0 40px; color: white; } .pg_header .pg_dl:hover{ background-color: #2459fb; cursor: pointer; } .left{ margin-top: 20px; width: 400px; display: inline-block; float: left; } .pg_body{ margin-top: 50px; font-size: 18px; display: inline-block; width: 200px; } .pg_body .menu{ width: 800px; padding: 15px; float: left; font-weight: bold; } input[type="text"]{ width: 200px; height: 25px; border-radius: 6px; } input[type="password"]{ width: 200px; height: 25px; border-radius: 6px; } input[type="button"]{ background-color: #555555; border: none; color: white; padding: 12px 29px; text-align: center; text-decoration: none; display: inline-block; font-size: 17px; margin: 4px 2px; cursor: pointer; border-radius: 4px; } input[type="submit"]{ background-color: #555555; border: none; color: white; padding: 12px 29px; text-align: center; text-decoration: none; display: inline-block; font-size: 17px; margin: 4px 2px; cursor: pointer; border-radius: 4px; } .kong{ margin-top: -54px; margin-left: 200px; float:left; padding: 15px; } .img{ width: 50px; height: 40px; } .can{ width: 1220px; height: 40px; line-height: 40px; margin: 0 auto; text-align: center; display: inline-block; } .tian{ color: red; float: right; font-size: 12px; margin-right: -120px; margin-top: -25px; } </style> </head> <body id="i88" style="margin: 0"> <div class = "pg_header"> <a class = "logo">LOGO</a> <a class="pg_dl" id="i77">注册</a> </div> <form name="tijiao" method="post" onsubmit="return check()" action="{% url 'App:register' %}"> {% csrf_token %} <div class="left"></div> <div class="pg_body"> <div class="menu">用户名:</div> <div class="kong"> <input id="text1" type="text" name="username" placeholder="请输入用户名" onblur="check()"><span id="div1" class="tian" style="margin-top: 4px">*(为必填)</span> </div> <div class="menu">密码:</div> <div class="kong"> <input id="text2" type="password" name="userpass" onblur="check()"> <span id="div2" class="tian" style="margin-top: 5px">*(为必填)</span> </div> <div class="menu">确认密码:</div> <div class="kong"> <input id="text3" type="password" name="01" onblur="check()"> <span id="div3" class="tian" style="margin-top: 5px">*(为必填)</span> </div> <div class="menu">邮箱地址:</div> <div class="kong"> <input id="text4" type="text" name="email" onblur="check()" required> <span id="div4" class="tian" style="margin-top: 5px">*(为必填)</span> </div> </div> <div class="can"> <input id="i111" type="submit" name="002" value="注 册"> <p style="width: 200px;display: inline-block;"></p> <input id="i222" type="button" name="004" value="取 消"> </div> </form> <script type="text/javascript"> //刷新or取消 document.getElementById('i77').onclick = function(){ location.reload(); } document.getElementById('i222').onclick = function(){ location.reload(); } //用户名验证 function checkname(){ var div = document.getElementById("div1"); div.innerHTML = ""; var name1 = document.tijiao.text1.value; if (name1 == "") { div.innerHTML = "用户名不能为空!"; document.tijiao.text1.focus(); return false; } if (name1.length < 4 || name1.length > 16) { div.innerHTML = "长度4-16个字符"; document.tijiao.text1.select(); return false; } var charname1 = name1.toLowerCase(); for (var i = 0; i < name1.length; i++) { var charname = charname1.charAt(i); if (!(charname >= 0 && charname <= 9) && (!(charname >= 'a' && charname <= 'z')) && (charname != '_')) { div.innerHTML = "用户名包含非法字符"; document.form1.text1.select(); return false; } } return true; } //密码验证 function checkpassword(){ var div = document.getElementById("div2"); div.innerHTML = ""; var password = document.tijiao.text2.value; if (password == "") { div.innerHTML = "密码不能为空"; {#document.tijao.text2.focus();#} return false; } if (password.length < 4 || password.length > 16) { div.innerHTML = "密码长度为4-16位"; document.tijiao.text2.select(); return false; } return true; } function checkrepassword(){ var div = document.getElementById("div3"); div.innerHTML = ""; var password = document.tijiao.text2.value; var repass = document.tijiao.text3.value; if (repass == "") { div.innerHTML = "密码不能为空"; document.tijiao.text3.focus(); return false; } if (password != repass) { div.innerHTML = "密码不一致"; document.tijiao.text3.select(); return false; } return true; } //邮箱验证 function checkEmail(){ var div = document.getElementById("div4"); div.innerHTML = ""; var email = document.tijiao.text4.value; var sw = email.indexOf("@", 0); var sw1 = email.indexOf(".", 0); var tt = sw1 - sw; if (email.length == 0) { div.innerHTML = "邮箱不能为空"; document.tijiao.text5.focus(); return false; } if (email.indexOf("@", 0) == -1) { div.innerHTML = "必须包含@符号"; document.tijiao.text5.select(); return false; } if (email.indexOf(".", 0) == -1) { div.innerHTML = "必须包含.符号"; document.tijiao.text5.select(); return false; } if (tt == 1) { div.innerHTML = "@和.不能一起"; document.tijiao.text5.select(); return false; } if (sw > sw1) { div.innerHTML = "@符号必须在.之前"; document.tijiao.text5.select(); return false; } else { return true; } return ture; } function check(){ if (checkname() && checkpassword() && checkrepassword() && checkEmail()) { return true; } else { return false; } } </script> </body> </html>
  • views.py

    from django.conf import settings # 导入配置 from django.shortcuts import render,HttpResponse,redirect,reverse from django.contrib.auth.models import User # 导入系统User模型 from django.contrib.auth import login,authenticate # 使用系统用户模型 以及方法 进行登录注册 退出登录等处理 def register(req): if req.method == 'POST': # 接受表单传递过来的数据 username = req.POST.get('username') userpass = req.POST.get('userpass') email = req.POST.get('email') try: # 用户的创建 User.objects.create_user(username,email,userpass) except: return HttpResponse('注册失败') return HttpResponse('注册成功') return render(req,'register.html')

五、认证用户

  • 导入

    from django.contrib.auth import login,authenticate

    login 处理用户登录状态的方法

    authenticate 认证用户的用户名和密码是否正确 正确返回用户对象 否则None

  • 视图函数

    from django.conf import settings # 导入配置 from django.shortcuts import render,HttpResponse,redirect,reverse from django.contrib.auth.models import User # 导入系统User模型 from django.contrib.auth import login,authenticate # 用户认证 登录 def Login(req): if req.method == 'POST': username = req.POST.get('username') userpass = req.POST.get('userpass') user = authenticate(username=username,password=userpass) # 认证成功返回对象 否则None if user: # 处理登录状态的维持 login(req,user) # 重定向到首页 return redirect(reverse('App:index')) else: return redirect(reverse('App:Login')) return render(req,'login.html')

    注意:如果该用户is_active为False 则认证失败

  • 在模板中判断是否登录

    Django自带的用户认证授权系统

    如果用户已经授权成功,说明用户已经登录成功,那么在渲染index.html的时候,直接展示已登录状态即可;如果用户认证失败,说明没有登录,那么在渲染index.html的时候,直接展示登录表单即可

    {% if request.user.is_authenticated %} <h3>登录了欢迎{{ request.user.username }}</h3> {% else %} <h3>没登录</h3> {% endif %}

六、修改用户密码

  • 方法

    set_password(new_password)

  • 说明

    修改密码是User的实例方法, 该方法不验证用户身份

    user.set_password(new_password)
  • 通常该方法需要和authenticate配合使用

    user = auth.authenticate(username=username, password=old_password) if user is not None: user.set_password(new_password) user.save()

七、视图函数获取登录用户对象

# 在视图函数中获取登录用户的数据 def own(req): # 判断是否登录 if req.user.is_authenticated: print(req.user.username) # 获取登录的用户名 print(req.user.last_login) # 上次登录时间 return HttpResponse('在视图函数中获取登录用户的数据')

八、退出登录

logout会移除request中的user信息, 并刷新session

from django.contrib.auth import logout def logout_view(request): logout(request) return redirect(reverse('App:index'))

九、权限判断(只允许登录用户访问)

@login_required修饰器修饰的view函数会先通过session key检查是否登录, 已登录用户可以正常的执行操作, 未登录用户将被重定向到login_url指定的位置。若未指定login_url参数, 则重定向到settings.LOGIN_URL

# 在视图函数中获取登录用户的数据 # 当前的own视图函数 必须登录才能访问 # @login_required(login_url='/system_login/') @login_required # 没有指定login_url 则会重定向到settings.py中指定的LOGIN_URL的路由地址 def own(req): # 判断是否登录 if req.user.is_authenticated: print(req.user.username) # 获取登录的用户名 print(req.user.last_login) # 上次登录时间 return HttpResponse('在视图函数中获取登录用户的数据')

配置全局 就不用再每一个装饰器添加了

settings.py

LOGIN_URL = ‘/login/’

十、自定义用户表

  • 给auth_user的模型表添加新字段 iphon和icon字段

  • models.py

    from django.contrib.auth.models import AbstractUser class User(AbstractUser): iphone = models.CharField(max_length=11,default=15611833906) icon = models.CharField(max_length=40,default='default.jpg')
  • 将用户模型设置为自己的模型

    AUTH_USER_MODEL = 'App.User'

    将迁移文件 和 库删除 在重新执行迁移

  • 添加自定义用户认证

    在App下新建一个auth.py

    auth.py

    from django.contrib.auth.backends import ModelBackend from django.db.models import Q from App.models import User class MyBackend(ModelBackend): def authenticate(self, username=None, password=None, **kwargs): user = User.objects.filter(Q(username=username)|Q(iphone=username)|Q(email=username)).first() if user: if user.check_password(password): return user return None

    注意:

    当认证失败的时候返回值只能为None否则报错

  • 在settings.py添加如下代码

    AUTHENTICATION_BACKENDS = ( 'App.auth.MyBackend', )
  • 视图代码更改为

    from App.models import User u = User.objects.create_user(username,email,userpass,iphone='18826123687')
需要 登录 才可以提问哦