32.Django中cookie和session

Django中的cookie和session同其他框架的概念是一样的。使用方式也大同小异。

基本概念

Cookies :是浏览器为 Web 服务器存储的一小段信息。 每次浏览器从某个服务器请求页面时,它收到服务器回发送过来的cookies。
Session:Django的Session机制会向请求的浏览器发送cookie字符串。同时也会保存到本地一份,用来验证浏览器登录是否为同一用户。它存在于服务器,Django默认会把session存入到数据库中

Session依赖于Cookie,如果浏览器不能保存cookies那么session就失效了。因为它需要浏览器的cookie值(sessionid)去session里做对比。session就是用来在服务器端保存用户的会话状态。

Cookie

基本使用

我们创建一个测试项目CookieSession以及Demo app。
url的配置略过。
在views.py中写:

from django.shortcuts import HttpResponse

def index(request):
    print(request.COOKIES) # 输出浏览器传过来的cookies
    return HttpResponse('hello litets.com')

启动服务器,在浏览器中输入` http://127.0.0.1:8000/' 然后会在控制台看到
可以看到打印出来的cookies是空的,这是因为我们没有返回给浏览器。

修改如下:

from django.shortcuts import HttpResponse


def index(request):
    print(request.COOKIES)
    resp =  HttpResponse('hello litets.com')
    resp.set_cookie('my_cookie', 'my_cookie_value', max_age=5) # 设置cookie
    return resp

然后刷新浏览器。Chrome按F12(或右键->检查)打开调试面板。 浏览器已经记录住我们下发的cookie。

如果快速刷新,可以在终端中看到

[26/Apr/2019 02:10:58] "GET / HTTP/1.1" 200 16
{'my_cookie': 'my_cookie_value'}

为什么要快速刷新才能看到呢,因为我们在设置cookie的时候设置max_age=5,单位是秒。

获取单个cookie上面我们打印的方式是一组cookie,实际就是一个dict,我们可以使用dict的方式, 获取到单个cookie。

from django.shortcuts import HttpResponse


def index(request):
    # 获取key为my_cookie的cookie
    # request.COOKIES.get() 方式如果key不存在,不会报错
    # request.COOKIES['key'] 方式如果key不存在,抛异常
    resp =  HttpResponse('hello litets.com  cookie=%s' % request.COOKIES.get('my_cookie'))
    resp.set_cookie('my_cookie', 'my_cookie_value', max_age=5)
    return resp

加密方式

cookie是存储在用户电脑的,当然不想被人拿到原文而出现安全问题。 通常都是要进行加密处理的。 Django提供一种方式方便我们使用,除了使用它原生方式,我们还可以自己实现,只要达到效果就好。

from django.shortcuts import HttpResponse


def index(request):
    resp =  HttpResponse('hello litets.com  cookie=%s' % request.get_signed_cookie('sign_key',default=None, salt='密钥'))
    resp.set_signed_cookie('sign_key', 'sign_value', salt='密钥', max_age=60)
    return resp

request.get_signed_cookie(key, default=RAISE_ERROR, salt='密钥', max_age=None):
获取解密后的实际值 rep.set_signed_cookie(key,value,salt='密钥',...):
设置加密的cookie。

Session

cookie和session是相对的,cookie存储在用户的浏览器,session存储在服务器,二者配合使用。

  • 数据库(默认)
  • 缓存
  • 文件
  • 缓存+数据库
  • 加密cookie

使用数据库

setting.py中配置使用什么方式:

SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
SESSION_COOKIE_NAME = "djSessionId"

此处使用默认的sqlites, 然后同步数据库:

python3 manage.py makemigrations
python3 manage.py migrate

views.py

from django.shortcuts import HttpResponse


def index(request):
    # 获取session
    resp =  HttpResponse('session=%s' % request.session.get('my_session', None))

    # 设置session
    request.session['my_session'] = 'w_session_value'
    return resp

刷新页面可以看到:

session=None 第一次刷新
session=w_session_value 再次刷新

浏览器中可以看到

我们打开db.sqlite3可以看到

可以在setting.py中配置的其他参数:

SESSION_COOKIE_NAME  "djSessionId" # Session的cookie保存在浏览器上时的key,即:djSessionId=随机字符串

SESSION_COOKIE_PATH  "/" # Session的cookie保存的路径(默认)

SESSION_COOKIE_DOMAIN = None  # Session的cookie保存的域名(默认)

SESSION_COOKIE_SECURE = False   # 是否Https传输cookie(默认)

SESSION_COOKIE_HTTPONLY = True   # 是否Session的cookie只支持http传输(默认)

SESSION_COOKIE_AGE = 1209600  # Session的cookie失效日期(2周)(默认)

SESSION_EXPIRE_AT_BROWSER_CLOSE = False  # 是否关闭浏览器使得Session过期(默认)

SESSION_SAVE_EVERY_REQUEST = False  # 是否每次请求都保存Session,默认修改之后才保存(默认)

读写session的api:

# 获取、设置、删除Session中数据
request.session['key']
request.session.get('key',None)
request.session['key'] = 123
request.session.setdefault('key',123) # 存在则不设置
del request.session['key']

# 所有 键、值、键值对
request.session.keys()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()

# 用户session的随机字符串
request.session.session_key

# 将所有Session失效日期小于当前日期的数据删除
request.session.clear_expired()

# 检查 用户session的随机字符串 在数据库中是否
request.session.exists("key")

# 删除当前用户的所有Session数据
request.session.delete("key")

使用缓存

SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
SESSION_CACHE_ALIAS = 'default'   # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置

使用文件

SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
SESSION_FILE_PATH = None  # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()

缓存+数据库Session

SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎

加密cookie Session

SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎

实例

views.py

from django.shortcuts import redirect, render


def login(request):
    if request.method == 'POST':
        name = request.POST['name']
        pwd = request.POST['pwd']

        if name == 'zhangsan' and pwd == '123':
            # 登陆成功将状态写入session
            request.session["logined"] = True
            request.session["user"] = name

    return redirect('/')


def index(request):

    # 从session中取值
    if request.session.get("logined", None):
        name = request.session.get("user", None)

    return render(request, "index.html", locals())

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
如果登陆了隐藏登陆表单
{% if  name is None %}
    <form action="/login/" method="post">
        {% csrf_token %}

        name: <input type="text" name="name">
        pwd: <input type="password" name="pwd">

        <input type="submit" value="登陆">
    </form>
{% endif %}

{{ name }}
</body>
</html>

未登录将会看到登录表单。使用zhangsan/123登录后表单将会消失,并且显示名称

声明:原创文章,版权所有,转载请注明出处,https://litets.com。