18-cookie和session

cookie

什么是cookie,cookie的应用场景及缺点

HTTP协议本身是”无状态”的,在一次请求和下一次请求之间没有任何状态保持,服务器无法识别来自同一用户的连续请求。有了cookie和session,服务器就可以利用它们记录客户端的访问状态了,这样用户就不用在每次访问不同页面都需要登录了。

cookie是一种数据存储技术, 它是将一段文本保存在客户端(浏览器或本地电脑)的一种技术,并且可以长时间的保存。当用户首次通过客户端访问服务器时,web服务器会发送给客户端的一小段信息。客户端浏览器会将这段信息以cookie形式保存在本地某个目录下的文件内。当客户端下次再发送请求时会自动将cookie也发送到服务器端,这样服务器端通过查验cookie内容就知道该客户端之前访问过了。

cookie的常见应用场景包括:

  • 判断用户是否已经登录
  • 记录用户登录信息(比如用户名,上次登录时间)
  • 记录用户搜索关键词

cookie的缺点在于其并不可靠和不安全,主要原因如下:

  • 浏览器不一定会保存服务器发来的cookie,用户可以通过设置选择是否禁用cookie。
  • cookie是有生命周期的(通过Expire设置),如果超过周期,cookie就会被清除。
  • HTTP数据通过明文发送,容易受到攻击,因此不能在cookie中存放敏感信息(比如信用卡号,密码等)。
  • cookie以文件形式存储在客户端,用户可以随意修改的。

在Django中如何操作cookie

即将render, HttpResponse, redirect实例化成一个对象,然后通过这个对象去操作即可

设置cookie

注意:Django的视图默认返回的response是不包含cookie的,需手动调用set_cookie方法。

response.set_cookie(cookie_name, value, max_age = None, expires = None) 

# key : cookie的名称
# value : 保存的cookie的值
# max_age: 保存的时间,以秒为单位
# expires: 过期时间,为datetime对象或时间字符串
# 方式1 不使用模板

response_obj = HttpResponse('注册成功')
response_obj.set_cookie("sign", '123')

# 方式2  重定向
obj = redirect("mybook:login")
obj.set_cookie(key="sign", value="112233", max_age=5)
return obj

# 方式3 使用模板
obj = render(request, 'mybook/demo_login.html')
obj.set_cookie(key='sign', value="112233", max_age=5)
return obj

获取cookie

# 方法一
request.COOKIES['username']

# 方法二
request.COOKIES.get('username','')

删除cookie

response.delete_cookie('username')

浏览器中查看cookie

image-20240311154030747

注册登录小验证

from django.shortcuts import render, HttpResponse, redirect
import hashlib

# md5加密
def encryption(username: str) -> str:
    return hashlib.new('md5', username.encode()).hexdigest()


# 测试demo
def demo(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username == "小满" and password == "123":
            response = redirect('mybook:login')
            # md5加密
            md5 = encryption(username)
            response.set_cookie(key="username", value=md5, max_age=60)
            return response
    return render(request, 'mybook/demo.html')

def login(request):
    if request.COOKIES.get("username", ''):
        return HttpResponse('登录成功')
    return HttpResponse('请先登录')

img

复用通过装饰器

def login_auth(func):
    def inner(request, *args, **kwargs):
        if request.COOKIES.get('username', ""):
            res = func(request, *args, **kwargs)
            return res
        else:
            base_path = reverse('mybook:demo')
            full_path = request.get_full_path()
            # 这里如果没有登录
            return redirect(f'{base_path}?next={full_path}')
    return inner

session

什么是session及session的工作原理

session又名会话,其功能与应用场景与cookie类似,用来存储少量的数据或信息。但由于数据存储在服务器上,而不是客户端上,所以比cookie更安全。不过当用户量非常大时,所有的会话信息都存储于服务器会对服务器造成一定的压力。

Django中如何使用会话session

  1. django中的session默认过期是14天
  2. 使用session的前提是迁移过数据库python manage.py makemigrations;
    1. 不然会报错
  3. 数据库对应的表一般是django_session;

第一步:检查基本设置

Django中使用session首选需要确保settings.py中已开启了SessionMiddleware中间件。

'django.contrib.sessions.middleware.SessionMiddleware',

Django默认使用数据库存储每个session的sessionid, 所以你还需确保INSTALLED_APPS 是包含如下app:

'django.contrib.sessions',

当然你还可以使用更快的文件或缓存来存储会话信息,可以通过SESSION_ENGINE设置就行。

第二步:使用session

request.session是一个字典,你可以在视图和模板中直接使用它。

# 设置session的值
request.session['key'] = value
request.session.set_expiry(time): # 设置过期时间 这个时间可以是一个整数,表示秒数,或一个datetime.timedelta对象,表示一段时间间隔
# 0表示浏览器关闭则失效  
# 设置会话过期时间为0意味着会话将在浏览器关闭时立即过期。
# 这样的设置使得会话只在当前浏览器会话期间有效,一旦用户关闭浏览器,会话将被删除并失效。

# 获取session的值
request.session.get('key',None)

# 删除session的值, 如果key不存在会报错
del request.session['key']
requeset.session.delete()  # 只会删除服务端 浏览器(客户端上面的不会删除)
request.session.flush()  # 客户端和服务端都删除  建议使用此方法

# 获取所有session的key和value
request.session.keys()
request.session.values()
request.session.items()

# 得到下面的结果
dict_keys(['username', '_session_expiry'])
dict_values(['2cb8e740ec7ba006709eea6adbf8da23', 55])
dict_items([('username', '2cb8e740ec7ba006709eea6adbf8da23'), ('_session_expiry', 55)])

完整案例

def demo(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username == "小满" and password == "123":
            # md5加密
            md5 = encryption(username)
            # 设置session为md5
            request.session['username'] = md5
            # 5秒过期
            request.session.set_expiry(5)
            return redirect('mybook:login')
    return render(request, 'mybook/demo.html')

def login(request):
    # 获取session
    if request.session.get('username', None):
        return HttpResponse('登录成功')
    return HttpResponse('请先登录')

另外,settings.py 还有两项有关session比较重要的设置:

  1. SESSION_COOKIE_AGE:以秒为单位,session的有效时间,可以通过set_expiry 方法覆盖。

  2. SESSION_EXPIRE_AT_BROWSER_CLOSE:默认为Flase,是否设置为浏览器关闭,会话自动失效。

基于session的小案例

登录成功后保存session,退出后删除session

# 注册
def demo(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username == "小满" and password == "123":
            # md5加密
            md5 = encryption(username)
            request.session['username'] = md5
            request.session.set_expiry(360)
            return redirect('mybook:login')
    return render(request, 'mybook/demo.html')


def login(request):
    if request.session.get('username', None):
        return render(request, 'mybook/demo_login.html')
    return HttpResponse('请先登录')
<!-- HTML -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h3>欢迎登录</h3>
    <a type="button" href="{% url 'mybook:logout' %}">退出系统</a>
    <script>
        let btn = document.querySelector('button');
        btn.onclick = function () {
            alert("您已经成功退出,期待再次相见!");
            // 关闭窗口
            window.close();
        };
    </script>
</body>
</html>

img

posted @ 2024-03-23 00:52  小满三岁啦  阅读(0)  评论(0编辑  收藏  举报