IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Django笔记6--装饰器、中间件实现Session限定访问 -> 正文阅读

[Python知识库]Django笔记6--装饰器、中间件实现Session限定访问

在有登录的系统中,有些页面可以不登录账户就可以访问,如:登录页、注册页等等,而有些网页则只能在登录成功之后才能跳转,如:个人信息主页,购物车页等等。
此时可以使用session记录登录状态来限制范围权限。
记录两种实现方法:
①在视图函数中,执行视图函数前,通过调用装饰器来获取session中的登录信息,判断是否登录成功,进而函数返回对应的页面。
②使用中间件,在接收到客户端访问请求时,获取session记录的登录信息,并对比客户端请求访问的路由,判断是否执行,未登录且访问需登录的网页,直接中断执行返回登录页,否则正常执行视图函数。

本案例中
登录页(login.html)、注册页(register.html)、退出页(loginout.html)可随意访问,
首页(index.html)、详情页(detail.html)需登录后访问.

具体方法见: 二、实现方法

一、搭建项目

1、创建项目

1、创建django项目

django-admin startproject Xxxx

2、创建数据库

create database Xxxx character set utf8;

3、项目内导入静态文件
在这里插入图片描述

4、配置项目
settings.py:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'LoginCS',
        'HOST': 'localhost',
        'USER': 'root',
        'PASSWORD': '123123',
        'PORT': '3306'
    }
}

STATICFILES_DIRS = [
    (os.path.join(BASE_DIR,'static')),
]

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR,'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

_ init _.py:

import pymysql

pymysql.install_as_MySQLdb()

2、创建应用

1、创建应用

python manage.py startapp Xxxx

2、注册应用
settings.py:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'user',
]

3、创建模型

3、迁移文件

1、生成迁移文件

python manage.py makemigrations

2、迁移

python manage.py migrate

4、配置路由

settings.py文件同级目录中的urls.py文件:

from django.conf.urls import url
from django.contrib import admin


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/',login),
    url(r'^loginout/',loginout),
]

5、创建视图函数

views.py:

import hashlib
import re

from django.http import HttpResponseRedirect
from django.shortcuts import render

# Create your views here.
from user.models import logininfo


def login(request):
    # 登录
    if request.method == 'GET':
        return render(request, 'login.html')
    else:
        # 接收客户端网页的数据
        uname = request.POST.get('use_rname')  # 与form表单中input标签的name属性一致
        pwd = request.POST.get('pdw')  # 与form表单中input标签的name属性一致
        cache = request.POST.get('cache')  # 与form表单中input标签的name属性一致
        # 再次校验数据,防止非法传递数据进视图
        if len(uname) < 5 or len(uname) > 20:
            return render(request,'login.html',{'errMsg':'用户名必须在5-20个字符'})
        elif len(pwd) < 8 or len(pwd) > 20:
            return render(request,'login.html',{
                'errMsg':'密码不符合规范,8-20个字符'
            })
        # 业务处理
        user = logininfo.objects.filter(username=uname)
        if user:
            # 存在该用户
            # 密码校验
            sha1=hashlib.sha256()
            sha1.update(pwd.encode('utf-8'))
            sha1_pwd = sha1.hexdigest()
            if user[0].pwd != sha1_pwd:  # user[0].pwd,pwd为数据表列名
                # 输入密码与数据库中的不匹配
                return render(request, 'login.html', {
                    'errMsg': '密码错误!'
                })
            else:
                res = HttpResponseRedirect('/')
                # 返回首页,设置cookie
                res.set_cookie('username',uname)
                # 返回首页,设置session
                request.session['is_login'] = True
                return res
        else:
            return render(request, 'login.html', {
                'errMsg': '用户未注册!'
            })

def register(request):
    # 注册
    if request.method == 'GET':
        return render(request, 'register.html')
    else:
        # 接收数据
        uname = request.POST.get('user_name')  # 与form表单中input标签的name属性一致
        pwd = request.POST.get('pwd')  # 与form表单中input标签的name属性一致
        confirmPwd = request.POST.get('cpwd')  # 与form表单中input标签的name属性一致
        email = request.POST.get('email')  # 与form表单中input标签的name属性一致
        allow = request.POST.get('allow')  # 与form表单中input标签的name属性一致
        # 检验数据
        if len(uname) < 5 or len(uname) > 20:
            return render(request, 'register.html', {
                'errMsg': '用户名必须在5-20个字符'
            })
        if len(pwd) < 8 or len(pwd) > 20:
            return render(request, 'register.html', {
                'errMsg': '密码不符合规范,8-20个字符'
            })
        if pwd != confirmPwd:
            return render(request, 'register.html', {
                'errMsg': '两次输入密码不一致'
            })

        if re.match('^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email) == None:
            return render(request, 'register.html', {
                'errMsg': '邮箱不符合规范'
            })

        if allow != 'on':
            return render(request, 'register.html', {
                'errMsg': '请同意网站协议'
            })
        # 业务处理
        # 查看数据库中是否已经有该用户名
        user = logininfo.objects.filter(username=uname)
        if user:
            return render(request, 'register.html', {
                'errMsg': '用户名已存在'
            })
        else:
            newUser = logininfo()
            newUser.username = uname
            # 加密匹配
            sha256 = hashlib.sha256()
            sha256.update(pwd.encode('utf-8'))
            sPwd = sha256.hexdigest()
            newUser.password = sPwd
            newUser.email = email
            newUser.is_active = 0
            newUser.save()
            # 返回响应
            return HttpResponseRedirect('/login')


def loginout(request):
    #清除session
    request.session.flush()
    return render(request,'login.html')
    
def index(request):
    # 首页
    return render(request, 'index.html')

def detail(request):
    # 详情
    return render(request, 'detail.html')

二、实现方法

1、装饰器实现访问限制

1、views.py同级目录中创建装饰器文件zsq.py:

from django.http import HttpResponseRedirect


def a(func):
    def inner(request):
    	# 获取路由传递给视图函数的request参数里的session数据
        is_login = request.session.get('is_login')  
        if is_login:  # 如果登陆状态is_login为Ture
            return func(request)  # 执行被装饰的视图函数
        else:
            return HttpResponseRedirect('/login') # 登陆状态is_login为False(默认值),返回登录页面
    return inner


2、views.py文件中引入装饰器并使用

from .zsq import a

@a
def index(request):
    # 首页
    return render(request, 'index.html')

@a
def detail(request):
    # 详情
    return render(request, 'detail.html')

此时浏览器直接访问
首页:http://127.0.0.1:8000/index/
详情页:http://127.0.0.1:8000/detail/
都将强制跳转到登录页面:http://127.0.0.1:8000/login/
只有登录成功后才能访问。

2、中间件实现限制访问

1、创建中间件文件Middleware.py:

#!/usr/bin/env python
from django.http import HttpResponseRedirect
from django.utils.deprecation import MiddlewareMixin

# 设置路由白名单
whiteUrls = ['/login/','/register/','/loginout/','/admin/']

class UserAuthMiddleWare(MiddlewareMixin):
    # 验证用户有没有登录 -
    def process_request(self,request):
        print(request.path)
        if request.path not in whiteUrls and request.path.startswith('/admin') == False:
            is_login = request.session.get('is_login',None)
            if not is_login:
                return HttpResponseRedirect('/login')

2、settings.py文件中注册创建的中间件:

MIDDLEWARE = [
	。。。。。
	# 对于settings.py文件而言的UserAuthMiddleWare函数路径
	# LoginCS/Middleware.py下的UserAuthMiddleWare()
    'LoginCS.Middleware.UserAuthMiddleWare',
]

3、注释前面使用的装饰器

from .zsq import a

# @a
def index(request):
    # 首页
    return render(request, 'index.html')

# @a
def detail(request):
    # 详情
    return render(request, 'detail.html')

此时浏览器直接访问
首页:http://127.0.0.1:8000/index/
详情页:http://127.0.0.1:8000/detail/
都将强制跳转到登录页面:http://127.0.0.1:8000/login/
只有登录成功后才能访问。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-12-23 15:43:22  更:2021-12-23 15:45:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 4:31:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码