资讯详情

9.Django 之 cookie 与 session

1. cookie 与 session

发展史: 1. 网站不保存用户信息,所有用户的访问返回结果都是一样的.(eg:新闻,博客) 2. 用户信息需要保存,所有用户的放回都是单独的.(eg:淘宝)  以登录功能为例:  如果不保存用户登录状态,这意味着用户每次访问网站都需要重复输入用户名密码.    当用户第一次成功登录时,将用户名和密码返回浏览器,在本地保存,  然后在访问该网站时,浏览器将自动向服务器发送用户名密码,自动验证服务. 
cookie:保存在客户端浏览器上的服务端信息可以称为cookie.  一帮是它的表现形式k:v键值对(可以有多个)  在早期,这种方法有很大的安全隐患.    优化:   当用户成功登录时,服务端生成随机字符串,保存客户端浏览器,    然后访问服务端时,都有随机字符串.服务端到数据库比较是否有相应的随机字符串  从而获应的用户信息.    截取字符串,然后你可以假装这个用户,仍有安全隐患. 
在web该领域没有绝对的安全性,没有绝对的不安全. 
session:数据保存在服务端,他的表现形式是一群k:v键值对(可以有多个) session 是基于cookie工作(大部分保存用户状态的操作都需要使用cookie). 
ps: token: session虽然保存在服务中,但经不起量大. 服务器不再保存数据,登录后,加密一段信息, 将加密的密文结果拼写在信息后面并保存到浏览器, 下次访问浏览器时,带信息, 服务端字段切断前一段信息,再次使用自己的加密算法与计算机尾部的密文进行比较.  jwt认证:(使用多)
三端信息

2. Cookie操作

虽然cookie是服务端告诉浏览器需要保存内容,但是客户端浏览器可以选择拒绝保存.
如果禁止了,只要是需要记录用户状态的网站登陆功能都无法使用.

image-20210822203306141

2.1 生成对象

# 视图函数的返回回值
return HttpResponse()
return render()
return redirec()

# 如果需要操作Cookit 需要变形操作

HttpResponse_obj =  HttpResponse()
return HttpResponse_obj

render_obj = render()
return render_obj

redirec_obj = redirec()
return redirec_obj

2.2 Cookie操作方法

# 设置cookie
obj.set_cookit(key, value)

# 获取 cookie()
request.COOKIES.get(key)

# 超时都是以秒为单位
为cookie设置一个超时时间,5秒到期
obj.set_cookit(key, value, max_age = 5)
# 针对ie浏览器
obj.set_cookit(key, value, expires=)

# 删除cookie
obj.delete_cookie(key) 

2.3 登入功能

写一个登入功能.
登入之后进入到主页
1. 路由层
from django.conf.urls import url
from django.contrib import admin
# 0. 导入视图层
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 1. 登入功能
    url(r'^login/', views.login),
    # 2. 主页
    url(r'^home/', views.home)
]
2. 视图层
# 登入功能 views.py
# 0. 导入 Django 三板斧
from django.shortcuts import render, redirect, HttpResponse

# Create your views here.


# 1. forms 组件定义
from django import forms


class MyForms(forms.Form):
    # 名称
    username = forms.CharField(
        label='名称',
        min_length=3, max_length=6,
        error_messages={ 
        
            'min_length': '名称过短',
            'max_length': '名称过长',
            'required': '名称不能为空'
        },
        widget=forms.widgets.TextInput(
            attrs=({ 
        'class': 'form-control'})
        )
    )

    # 密码
    password = forms.CharField(
        label='密码',
        min_length=3,
        max_length=11,
        error_messages={ 
        
            'min_length': '密码过短',
            'max_length': '密码过长',
            'required': '名称不能为空'
        },
        widget=forms.widgets.PasswordInput(
            attrs=({ 
        'class': 'form-control'})
        )
    )


# 2. 登入函数
def login(request):

    # 2.1 forms对象
    forms_obj = MyForms()

    # 2.3 判断请求方式
    if request.method == 'POST':
        print(request.POST)
        # 2.4 检验密码 字符串类型比对
        if request.POST.get('username') == 'kid' and request.POST.get('password') == '123':
            return redirect('/home/')
        else:
            forms_obj = MyForms(request.POST)

    # 2.2 返回登入页面 和 forms组件对象
    return render(request, 'login.html', locals())


# 3. 主页
def home(request):
    return render(request, 'home.html')
3. 前端页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登入功能</title>
    <!--0. 动态获取静态文件名称 -->
    {% load static %}
    <!--1. 导入jQuery js 文件-->
    <script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
    <!--2. 导入 bootstrap css 文件-->
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
    <!--3. 导入 bootstrap js 文件-->
    <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div>
    <!--4. form表单 post请求 前端不验证 -->
    <form action="" method="post" novalidate>
        {% for form in forms_obj %}
        <p>{
    
       { form.label }}:{
    
       { form }} <span style="color: red;">{
    
       { form.errors.0 }}</span></p>
        {% endfor %}
        <input type="submit">
    </form>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
    <div>
        我是主页
    </div>
</body>
</html>
0. 浏览器中输入 127.0.0.1/login  登入页面中 输入 名称 密码 进去主页.
1. 浏览器中输入 127.0.0.1/home   直接访问.
4. 设置cookie
在登入验证处设置 cookie 信息	
        # 2.5 检验密码 字符串类型比对
        if username == 'kid' and password == '123':

            # 2.6 cookie 操作
            """ 1. 生成对象 2. 设置cookie 3. 返回对象 """
            redirect_obj = redirect('/home/')
            redirect_obj.set_cookie('username', 'kid666')
            return redirect_obj
# 2. 登入函数
def login(request):
    # 2.1 forms对象
    forms_obj = MyForms()

    # 2.3 判断请求方式
    if request.method == 'POST':
        print(request.POST)

        # 2.4 获取post提交的数据
        username = request.POST.get('username')
        password = request.POST.get('password')

        # 2.5 检验密码 字符串类型比对
        if username == 'kid' and password == '123':

            # 2.6 cookie 操作
            """ 1. 生成对象 2. 设置cookie 3. 返回对象 """
            redirect_obj = redirect('/home/')
            redirect_obj.set_cookie('username', 'kid666')
            return redirect_obj

        else:
            forms_obj = MyForms(request.POST)

    # 2.2 返回登入页面 和 forms组件对象
    return render(request, 'login.html', locals())
* 设置cookie后在测试, 测试前对cookie清除.

0. 浏览器中输入 127.0.0.1/login  登入页面中 输入 名称 密码 进去主页.
查看到cookie中有数据.
cookie 中有数据

1. 浏览器中输入 127.0.0.1/home   直接访问.
cookie 是没有数据的. 显示非法访问

5. 获取cookie数据
cookie数据被保存到request中
通过request.COOKIES.get('key') 获取值

如果能获取到数据那说明是通过登入页面正常输入账户密码进入主页的,
不然就直接访问的.
# 3. 主页
def home(request):
    # 3.2 获取request中的cookie数据
    if request.COOKIES.get('username') == 'kid666':

        # 3.1 返回主页
        return render(request, 'home.html')
    else:
        # 3.2 返回提示信息
        return HttpResponse('非法访问')
0. 浏览器中输入 127.0.0.1/login  登入页面中 输入 名称 密码 进去主页.
cookie 中有数据

1. 浏览器中输入 127.0.0.1/home   直接访问.
cookie 是没有数据的.

6. 检验装饰器
如果有多个需要验证才能进入的页面,就可以制作一个校验信息的登入装饰器.
   # urls.py 
    # 3. 需要验证才能登入的网页1
    url(r'^index1', views.),
    # 4. 需要验证才能登入的网页2
    url(r'^index2', views.index2),
    # 5. 需要验证才能登入的网页3
    url(r'^index3', views.index2)
# 4. 登入验证
def verification(func):
    def inner(request, *args, **kwargs):
        # 验证cookie中的数据
        if request.COOKIES.get('username') == 'kid666':
            res = func(request, *args, **kwargs)
            return res
        else:
            return redirect('/login/')
    return inner


# 5. 需要验证才能登入的网页1
@verification
def index1(request):
    return HttpResponse('需要验证才能登入的网页1')


# 6. 需要验证才能登入的网页2
@verification
def index2(request):
    return HttpResponse('需要验证才能登入的网页2')


# 7. 需要验证才能登入的网页3
@verification
def index3(request):
    return HttpResponse('需要验证才能登入的网页3')
在没有cookie中没有数据的时候是无法直接进入到
index1 index2 index3 的页面

被重定向到login功能中,要求登入...

输入正确的用户和密码.

只有当cookie有了数据,并且数据符合要求,
就能够直接访问 index1 index2 index3 的页面.

7. 登入返回
现在存在的问题是 cookie中没有数据 进入 127.0.0.1/index1 2 3
跳转到登入页面,成功登入之后,应该返回用户之前想要访问的页面去.
而不是进入了home页面.
request.path 
提供相对于根目录的url相对路径,不包含参数。它的输出是一个字符串
/index1
request.path_info
提供相对于根目录的url相对路径,不包含参数。它的输出也是一个字符串,与request.path相同.
/index1
request.get_full_path() 
获取包含完整参数的相对于根目录的相对url路径。
/index1/?name=kid
request.build_absolute_uri()
该方法用于获取带域名的url绝对路径, 是一个字符串.
http://127.0.0.1:8000/index1/?name=kid

# 进入登入页面的时候携带我们要访问的url
target_url = request.get_full_path()
return redirect('/login/?next=%s' % target_url)
# 4. 登入验证
def verification(func):
    def inner(request, *args, **kwargs):
        # 4.1 验证cookie的数据
        if request.COOKIES.get('username') == 'kid666':
            # 4.1 验证通过执行被装饰的函数 index 1 2 3
            res = func(request, *args, **kwargs)
            return res
        else:
            # 4.2 获取输入的地址
            target_url = request.get_full_path()
            return redirect('/login/?next=%s' % target_url)
    return inner

当前的form表单的提交方式是post
<!--4. form表单 post请求 前端不验证 -->
<form action="" method="post" novalidate>
# 2. 登入函数
def login(request):
    # 2.1 forms对象
    forms_obj = MyForms()

    # 2.3 判断请求方式
    if request.method == 'POST':
        print(request.POST)

        # 2.4 获取post提交的数据
        username = request.POST.get('username')
        password = request.POST.get('password')

        # 2.5 检验密码 字符串类型比对
        if username == 'kid' and password == '123':

            # 2.6 获取根目录地址
            target_url = request.GET.get('next')
            print(target_url)

            # 2.7 cookie 操作 如果获取到地址就把这个地址作为参数,没有获取到地址就访问到主页.
            if target_url:
                redirect_obj = redirect(target_url)
            else:
                redirect_obj = redirect('/home/')
            redirect_obj.set_cookie('username', 'kid666')

            return redirect_obj

        else:
            forms_obj = MyForms(request.POST)

    # 2.2 返回登入页面 和 forms组件对象
    return render(request, 'login.html', locals())

8. 注销时清除cookie
    # urls.py 
    # 6. 注销
    url(r'^logout/', views.logout)
# views.py
# 5. 需要验证才能登入的网页1
@verification
def index1(request):
    return render(request, 'index1.html')
# views.py
# 8. 注销 (只有登入的用户才能注销) 注销之后退回到登入页面中去
@verification
def logout(request):
    # 8.1 生成对象
    redirect_obj = redirect('/login/')
    # 8.2 清除cookie中指定的数据
    redirect_obj.delete_cookie('username')
    # 8.3 返回对象
    return redirect_obj
<li><a href="/logout/">退出登入</a></li>  绑定logout
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index1</title>
        <!--0. 动态获取静态文件名称 -->
    {% load static %}
    <!--1. 导入jQuery js 文件-->
    <script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
    
        标签: 2472d05po光电传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台