阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

高阶应用-用户验证

135次阅读
没有评论

共计 9518 个字符,预计需要花费 24 分钟才能阅读完成。

一、说明

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')

正文完
星哥说事-微信公众号
post-qrcode
 
星锅
版权声明:本站原创文章,由 星锅 2022-05-26发表,共计9518字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中