Django框架 - 09 实现登陆注册注销

一. 登录/注册/登录状态权限验证

前言

通过cookie和token去实现登录功能,用户在登录账号以后,随机产生一个随机数并存在cookie中,并在服务端也存储同一个数在数据库中。当下一次url请求过来的时候,解析request中绑定的cookie信息,解锁出之前存的随机数,判断该随机数是否是存储在服务器端的数据,如果没有查询到则表示该cookie过期,或者该cookie是伪造的,或者服务器上存储该信息的数据缓存到期被清空了。则该提示用户重新登录,并且重新产生随机数,并存储在cookie中以及服务端,以保证下次请求和响应能够顺利。

练手题目

题目:
1) 编写一个方法,用于注册用户的账号和密码。

2) 编写一个方法,用于登录用户的账号和密码,并且登录的时候绑定一个加密的参数在cookie上,并且该加密参数也存储在服务端中。

3)在以后的任意一个请求,我们都获取request中的cookies,查看cookie中绑定的参数是否合法,以及查询是否在服务端存储了。

4)如果验证成功则返回请求url的结果信息到页面,如果验证失败则返回错误提醒信息页面

5) 注销登录

6)定义装饰器去验证用户登录以后才执行对应的视图函数,反之跳转到登录页面中

1. 注册方法

从页面中获取账号和密码,进行创建
这里写图片描述

2. 登录,并且绑定参数到cookie上

先检验用户名是否在数据库中,如果查询到则继续验证密码, 如果密码验证对,则绑定一个参数到cookie中。
解析密码,加密密码来源与一下的模块:

from django.contrib.auth.hashers import check_password, make_password

这里写图片描述

3. 在方法中验证cookie中传递的参数是否正确

cookie是在用户提交url请求的时候都会带上的一个参数,所以可以从中获取到我们设置的参数,并且在服务端进行验证,看服务端有这个标识符没有,
如果能查询到,则表示用户登录过了,并且还在登录时效内,则直接返回用户提交url对应的响应。如果在服务端没有查询到数据,则表示标识符过期,
或者无效了,需要登录了,则直接提示错误信息即可!
这里写图片描述

4. 注销登录

删除cookie中的认证令牌
这里写图片描述

扫描二维码关注公众号,回复: 3141839 查看本文章

5. 通过定义装饰器去验证用户是否是登录状态,如果不是,则跳转到登录

定义装饰器–闭包
这里写图片描述

二. Django自带方法实现登录/注册/登录状态权限

前言

在django中,django帮我们封装好了登录注册以及注销的函数,使用django定义好的注册登录注销函数去实现用户的登录验证,用户登录,以及用户注销等操作,以及定义login_rqueired装饰器,去装饰我们定义的函数,实现登录才能处理对应的业务逻辑

1. 实现注册方法

1.1 页面提交注册字段

在页面的form中有一下三个字段,用户名和密码1和密码2,页面在submit提交的时候,会提交该三个字段后后端,在后端中获取该参数即可
这里写图片描述

1.2 后端处理注册的信息

后端获取前端传递的参数,进行简单的验证后,进行创建用户的信息
这里写图片描述

2. 实现登录方法

2.1 登录页面提交登录的字段

这里写图片描述

2.2 后端进行登录的验证

这里写图片描述

3. 实现注销方法

这里写图片描述

4. 登录验证

from django.contrib.auth.decorators import login_required

使用login_required装饰器去装饰自定义的视图函数

5. 手动实现登陆注册具体代码

from datetime import datetime, timedelta

from django.contrib.auth.hashers import make_password, check_password
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.core.urlresolvers import reverse

from sx_user.models import UserModel, UserTicketModel
from utils.functions import get_ticket


# 注册
def register(request):
    if request.method == 'GET':
        return render(request, 'register.html')

    if request.method == 'POST':
        username = request.POST.get('user_name')
        password = request.POST.get('pwd')
        password_c = request.POST.get('cpwd')
        email = request.POST.get('email')
        # 验证参数都不能为空
        if not all([username, password, password_c, email]):
            data = {
                'msg': '请填写完整的信息'
            }
            return render(request, 'register.html', data)
        # 加密password
        password = make_password(password)
        password_c = make_password(password_c)
        # 创建用户并添加到数据库
        UserModel.objects.create(username=username,
                                 password=password,
                                 password_c=password_c,
                                 email=email)
        # 注册成功跳转到登陆页面
        return HttpResponseRedirect(reverse('user:login'))


# 登陆
def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')

    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('pwd')
        data = {}
        # 验证信息是否填写完整
        if not all([username, password]):
            data['msg'] = '请填写完整的用户名或密码'
        # 验证用户是否注册
        if UserModel.objects.filter(username=username).exists():
            user = UserModel.objects.get(username=username)
            # 验证密码是否正确
            if check_password(password, user.password):
                # 如果密码正确将ticket值保存在cookie中
                ticket = get_ticket()
                response = HttpResponseRedirect(reverse('store:index'))
                out_time = datetime.now() + timedelta(days=2)
                response.set_cookie('ticket', ticket, expires=out_time)
                # 保存ticket值到数据库user_ticket表中
                UserTicketModel.objects.create(user=user,
                                               out_time=out_time,
                                               ticket=ticket)
                return response
            else:
                msg = '用户名或密码错误'
                return render(request, 'login.html', {'msg': msg})
        else:
            msg = '用户名不存在,请注册后在登陆'
            return render(request, 'login.html', {'msg': msg})


# 退出
def logout(request):
    if request.method == 'GET':
        # 退出则删除数据库中的ticket值
        ticket = request.COOKIES.get('ticket')
        user_ticket = UserTicketModel.objects.filter(ticket=ticket).first()
        UserTicketModel.objects.filter(user=user_ticket.user).delete()
        return HttpResponseRedirect(reverse('user:login'))


# 中间件
from datetime import datetime

from django.db.models import Q
from django.http import HttpResponseRedirect
from django.utils.deprecation import MiddlewareMixin
from django.core.urlresolvers import reverse

from user.models import UserTicketModel, UserModel


class UserMiddle(MiddlewareMixin):

    def process_request(self, request):

        # 需要登录验证,个人中心和购物车和商品的增删
        need_login = ['/tb/index/', 
                      '/tb/list/',]
        if request.path in need_login:
            # 先获取cookies中的ticket参数
            ticket = request.COOKIES.get('ticket')
            # 如果没有ticket,则直接跳转到登录
            if not ticket:
                return HttpResponseRedirect(reverse('user:login'))

            user_ticket = UserTicketModel.objects.filter(ticket=ticket).first()
            if user_ticket:
                # 获取到有认证的相关信息
                # 1. 验证当前认证信息是否过期,如果没过期,request.user赋值
                # 2. 如果过期了,跳转到登录,并删除认证信息
                if datetime.utcnow() > user_ticket.out_time.replace(tzinfo=None):
                    # 过期
                    UserTicketModel.objects.filter(user=user_ticket.user).delete()
                    return HttpResponseRedirect(reverse('user:login'))
                else:
                    # 没有过期,赋值request.user,并且删除多余的认证信息
                    request.user = user_ticket.user
                    # 删除多余的认证信息,
                    # 从UserTicket中查询当前user,并且ticket不等于cookie中的ticket
                    UserTicketModel.objects.filter(Q(user=user_ticket.user) &
                                                   ~Q(ticket=ticket)).delete()
                    return None
            else:
                return HttpResponseRedirect(reverse('user:login'))
        else:
            return None

猜你喜欢

转载自blog.csdn.net/hanbo6/article/details/82527984