第七章 Django用户认证与会话技术

2023-12-14 21:36:36

第一章 Django 基本使用
第二章 Django URL路由系统
第三章 Django 视图系统
第四章 Django 模板系统
第五章 Django 数据模型系统(基本使用)
第六章 Django 数据模型系统(多表操作)
第七章 Django 用户认证与会话技术
第八章 Django CSRF防护



内置用户认证系统

介绍

Django内置的用户认证系统基于auth模块实现

auth模块提供了登录、注册、校检、修改密码、注销、验证用户是否登录等功能。

主要包括以下几个部分:

  • 用户模型(User Model):Django提供了一个默认的用户模型,可以根据需要自定义字段。要使用这个模型,需要在settings.py中设置AUTH_USER_MODEL'auth.User'
  • 认证后端(Authentication Backends):Django支持多种认证后端,如数据库、LDAP等。要使用某个认证后端,需要在settings.py中设置AUTHENTICATION_BACKENDS
  • 视图和URL配置:Django提供了一些视图和URL模式来处理用户认证相关的请求,如登录、注册、密码重置等。需要在urls.py中添加相应的URL模式
  • 模板和表单:Django提供了一些模板和表单用于显示认证相关的页面,如登录、注册等。可以在模板中使用这些表单
登录
退出
用户信息认证
登录认证装饰器
获取登录用户信息
扩展auth_user表字段
auth
login
logout
authenticate
decorators
login_required
models
user
BaseUserManage,AbstractBaseUser

Django默认创建的数据库表包括

  1. auth_user:用户表,用于存储用户的身份验证信息。

  2. auth_user_groups:用户所属组的表,用于存储用户与用户组之间的关系。

  3. auth_user_user_permissions:用户权限表,用于存储用户的权限信息。

  4. auth_group:用户组表,用于存储用户组的信息。

  5. auth_group_permissions:用户组权限表,用于存储用户组的权限信息。

  6. auth_permission:存放全部权限的表,其他的表的权限都是从此表中外键连接过去的。

  7. django_session:保存HTTP状态的表。

  8. django_migrations:数据库迁移记录的表

    image-20231204150133057

auth模块使用

login&logout

准备工作

http://49.232.221.200:8080/admin/auth/user/

image-20231204214306991

image-20231204214349011

image-20231204214434699

image-20231204214443855

image-20231204214557943

路由

# myorm/urls.py
from django.urls import include, path, re_path
from myorm import views
from .views import view_course_students,edit_student,drop_student
urlpatterns = [
    path('login/', views.login, name='login'),
    path('home_page/', views.home_page, name='home_page'),
    path('logout/', views.logout, name='logout'),
]

视图

# myorm/views.py
from django.shortcuts import render, get_object_or_404,redirect,HttpResponse
from .models import Course, Student
from django.contrib import auth    


def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    elif request.method == "POST":
        username = request.POST.get("username",None)
        password = request.POST.get("password",None)
        # 对用户数据验证
        user = auth.authenticate(username=username, password=password)
        # 如果效验成功,返回一个用户对象,否则返回一个None
        if user:
            # 验证通过后,将request与用户对象(包含session)传给login()函数
            auth.login(request, user)
            # 跳转到http://49.232.221.200:8080/myorm/home_page
            return redirect("home_page")
        else:
            mag = '用户名密码错误'
        return render(request, "login.html",{'mag': mag})

def home_page(request):
    return render(request,"home_page.html")

def logout(request):
    # 清除当前用户的session信息
    auth.logout(request)
    return redirect('login')

网页

<!-- myrom/templates/login.html -->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>登录</title>
    </head>
    <body>
        <form action="" method="post">
            <h1>登录</h1>
            用户名:<input type="text" name="username"><br>
            密码:<input type="text" name="password"><br>
            <button type="submit">登录</button>
        </form><br>
        <span style="color: red;">{{ mag }}</span>
    </body>
</html>
<!-- myrom/templates/home_page.html -->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>标题</title>
    </head>
    <body>
        
        <h1>欢迎访问首页</h1>
        <a href="/myorm/logout">退出</a>
    </body>
</html>

验证

登录成功会有一个session的会话记录,退出后就没有了

http://49.232.221.200:8080/myorm/login/

image-20231204220353173

image-20231204220405776

image-20231204220421862

登录认证装饰器

login_required装饰器通常用于Django框架中,用于确保用户在访问某个视图函数之前已经登录。当用户未登录时,他们将被重定向到登录页面

路由

# myorm/urls.py
from django.urls import include, path, re_path
from myorm import views
from .views import view_course_students,edit_student,drop_student
urlpatterns = [
    path('login/', views.login, name='login'),
    path('home_page/', views.home_page, name='home_page'),
    path('logout/', views.logout, name='logout'),
]

视图

# myorm/views.py
from django.shortcuts import render, get_object_or_404,redirect,HttpResponse
from .models import Course, Student
from django.contrib import auth
from django.contrib.auth.decorators import login_required


def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    elif request.method == "POST":
        username = request.POST.get("username",None)
        password = request.POST.get("password",None)
        # 对用户数据验证
        user = auth.authenticate(username=username, password=password)
        # 如果效验成功,返回一个用户对象,否则返回一个None
        if user:
            # 验证通过后,将request与用户对象(包含session)传给login()函数
            auth.login(request, user)
            # 跳转到http://49.232.221.200:8080/myorm/home_page
            return redirect("home_page")
        else:
            mag = '用户名密码错误'
        return render(request, "login.html",{'mag': mag})
# 加入这个配置
@login_required()
def home_page(request):
    return render(request,"home_page.html")

def logout(request):
    # 清除当前用户的session信息
    auth.logout(request)
    return redirect('login')

网页

<!-- myrom/templates/login.html -->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>登录</title>
    </head>
    <body>
        <form action="" method="post">
            <h1>登录</h1>
            用户名:<input type="text" name="username"><br>
            密码:<input type="text" name="password"><br>
            <button type="submit">登录</button>
        </form><br>
        <span style="color: red;">{{ mag }}</span>
    </body>
</html>
<!-- myrom/templates/home_page.html -->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>标题</title>
    </head>
    <body>
        
        <h1>欢迎访问首页</h1>
        <a href="/myorm/logout">退出</a>
    </body>
</html>

验证

没有加入@login_required()时候可以直接访问

http://49.232.221.200:8080/myorm/home_page/

image-20231204221448195

加入@login_required()

没有登录的话,访问是直接报错的

image-20231204221546367

解决报错

# orm/setting.py
# 在settings.py最下边文件设置没有登录默认跳转页面:
LOGIN_URL = '/myorm/login'

访问http://49.232.221.200:8080/myorm/home_page/跳转到了登录界面

image-20231204221753143

Session管理

Session与Cookie是什么

Cookie和Session都是Web程序中跟踪用户会话的关键技术。它们都使得HTTP协议具备了状态,能记录和跟踪用户的整个会话过程。

Cookie是存储在客户端的一种数据结构,形如"name=value"的变量。它是服务器发送到用户浏览器并保存在浏览器上的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,Cookie用来跟踪会话,也可以保存用户的喜好或者保存用户名密码等信息。

Session则是存储在服务器端的一种数据结构,通常是一个映射(键值对)。当用户访问服务器时,服务器会为该用户创建一个session对象,用于存储该用户的信息。这个session对象包含了所有需要记录用户状态的信息,比如用户的登录状态、用户的名称等等。一个sessionID会被保存在客户端的Cookie中,这样当浏览器再次访问服务器时,服务器就能通过读取Cookie中的sessionID来识别用户。

总结来说,Cookie和Session都是为了在客户端与服务器之间保持会话所需要的一种技术。两者的主要区别在于:Cookie将信息保存在客户端,而Session则将信息保存在服务器端。

举例

假设你在使用一个网站,首先你需要输入用户名和密码进行登录。此时,你的浏览器会向服务器发送一个包含这些信息的POST请求。服务器接收到请求后,会在响应头中添加一条"set-cookie: JSESSIONID"字段,这条信息是用于记录你的用户信息。同时,服务器还会创建一个session对象来保存你的登录状态等信息。

随后,服务器会把包含Session信息的Cookie发回给你的浏览器。你的浏览器接收到这个Cookie后,会将其保存在磁盘上。这意味着,下次你再次访问服务器时,浏览器会自动携带这个Cookie信息。服务器通过读取这个Cookie中的SessionID来识别你,并获取你的登录状态等信息。

这样,客户端和服务端就实现了会话跟踪。无论是点击多个超链接还是关闭再重新打开浏览器,只要SessionID未过期或被清除,你的登录状态都能得到保持。

会话管理
Cookie
数据存储再浏览器端
特点
方便与js交换数据
方便获取用户信息
风险
浏览器可能会禁用Cookie
Session
数据存储在服务端
特点
高效
安全
不依赖浏览器环境
服务器端会为每一个用户分配一个ID标识

使用Session

在settings.py配置文件中设置客户端Cookie:

参数描述
SESSION_COOKIE_NAME = “sessionid”Session的cookie保存在浏览器上时的key
即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = “/”Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = NoneSession的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST = False是否每次请求都保存Session,默认修改之后才保存(默认)

在视图中操作Session:

参数描述
request.session[‘key’] = value向Session写入键值
request.session.get(‘key’,None)获取Session中键的值
request.session.flush()清除Session数据
request.session.set_expiry(value)Session过期时间

示例

# orm/setting.py
# 最下边添加
# 调整过期时间为60秒
SESSION_COOKIE_AGE = 60

image-20231205095941296

写个登录案例

准备工作

user表增加一个字段

# myorm/models.py
from django.db import models

# Create your models here.
# 定义一个用户表,继承model类
class User(models.Model):
    user = models.CharField(max_length=30) # 定义user字段,并定义为字符串以及设置长度
    name = models.CharField(max_length=30) # 定义name字段,并定义为字符串以及设置长度
    sex = models.CharField(max_length=10) # 定义sex字段,并定义为字符串以及设置长度
    age = models.IntegerField() # 定义age字段,并定义为整型
    label = models.CharField(max_length=100) # 定义label字段,并定义为字符串以及设置长度
    password = models.CharField(max_length=100, default='123456',verbose_name="密码")  # 增加的字段,默认是123456
    
    class Meta:
        app_label = "myorm" # 指定APP名称
        db_table = 'user'   # 自定义生成的表名
        managed = True     # Django自动管理数据库表
        verbose_name = '用户表'  # 对象的可读名称
        verbose_name_plural = '用户表'  # 名称复数形式
        ordering = ["sex"] # 对象的默认顺序,用于获取对象列表时

    def __str__(self):
        return self.name
python3 manage.py makemigrations
python3 manage.py migrate

image-20231205101019443

路由

# myorm/urls.py
from django.urls import include, path, re_path
from myorm import views
urlpatterns = [
    path('login/', views.login, name='login'),
    path('home_page/', views.home_page, name='home_page'),
    path('logout/', views.logout, name='logout'),
]

视图

# myorm/views.py
from django.shortcuts import render, get_object_or_404,redirect,HttpResponse
from .models import Course, Student
from django.contrib import auth
from django.contrib.auth.decorators import login_required


# 定义一个装饰器
def self_login_required(func):
    def inner(request):
        is_login = request.session.get('is_login', False)
        if not is_login:
            return redirect(login)
        else:
            return func(request)
    return inner

@self_login_required
def home_page(request):
    return render(request,"home_page.html")

def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    elif request.method == "POST":
        username = request.POST.get("username",None)
        password = request.POST.get("password",None)
        # 对用户数据验证
        user = User.objects.filter(user=username)
        if user:
            for i in user:
                passwd = i.password
            if password == passwd:
                # 验证通过后,将request与用户对象(包含session)传给login()函数
                request.session['is_login'] =True
                request.session['username'] = username
                # 跳转到http://49.232.221.200:8080/myorm/home_page
                return redirect("home_page")
            else:
                mag = '用户名密码错误'
        else:
            mag = '用户名密码错误'
        return render(request, "login.html",{'mag': mag})

def logout(request):
    # 清除当前用户的session信息
    auth.logout(request)
    return redirect('login')

网页

<!-- myrom/templates/login.html -->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>登录</title>
    </head>
    <body>
        <form action="" method="post">
            <h1>登录</h1>
            用户名:<input type="text" name="username"><br>
            密码:<input type="text" name="password"><br>
            <button type="submit">登录</button>
        </form><br>
        <span style="color: red;">{{ mag }}</span>
    </body>
</html>
<!-- myrom/templates/home_page.html -->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>标题</title>
    </head>
    <body>
        
        <h1>欢迎访问首页</h1>
        <a href="/myorm/logout">退出</a>
    </body>
</html>

验证

http://49.232.221.200:8080/myorm/login/

账户名密码就是user表中的数据

image-20231205103033181

退出后没有session的记录了

image-20231205103102519

@self_login_required
def home_page(request):

上加了装饰器,那么无法直接访问http://49.232.221.200:8080/myorm/home_page/,需要登录在进行访问

文章来源:https://blog.csdn.net/weixin_42434700/article/details/135003566
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。