Cookie和Session

Posted accolade

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cookie和Session相关的知识,希望对你有一定的参考价值。

老师的博客:https://www.cnblogs.com/liwenzhou/p/8343243.html

 Cookie

什么是cookie

它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。

查看Cookie

技术图片

输出上面的cookie

print(request.COOKIRES)
{csrftoken: Jm5yoqvBHgCN5ejKIUB2auRqamtBtQHCnmWzNXALTHIa49LJDJTIP7uO4cPTHGOx}得到的是个字典

 request cookies是得到的键值对

response cookies是在函数中放生了调用,删除,改变的等操作的键值对

Django中操作Cookie

获取Cookie

request.COOKIES[key]
request.get_signed_cookie(key, default=RAISE_ERROR, salt=‘‘, max_age=None)

参数:

  • key, 键
  • value=‘‘, 值
  • max_age=None, 超时时间,单位是秒
  • expires=None, 超时时间(IE requires expires, so set it if hasn‘t been already.)
  • path=‘/‘, Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问
  • domain=None, Cookie生效的域名
  • secure=False, https传输
  • httponly=False 只能http协议传输,无法被javascript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

设置Cookie

已登陆页面为例

def login(request):
    if request.method=="POST":
        user=request.POST.get(user)
        psd=request.POST.get("password")
        print(request.POST)
        print(request.COOKIES)
        if user=="lhy" and psd=="mmd":
        #验证成功 rep
=redirect("/main/")#跳转到一个相应对象 rep.set_cookie("xpg","mmd",max_age=None)#给对象设置个Cookie
       
return rep return render(request,"login.html")

 取得方法:

ret = request.COOKIES.get("xpg", None)

 

然后你就可以查看里面的cookie有你添加的键值对了

 当然还有种添加cookie的方法:(加盐的)

rep.set_signed_cookie("alex","teacher",salt="大苹果", max_age=None)
max_age表示cookie保存的时间,默认是关闭浏览器就删除键值对

 取值得方法:

ret = request.get_signed_cookie("xpg", salt=大苹果, max_age=None)

 

这种方法多了个加盐的过程,我看了下代码,还是return到上面的那种方法

当然一个可以对于一个相应对象,可以添加多个键值对。

注意:

  • 如果向一个网站多次添加键值对是,这是键值对的键不一样就会一直存在(如果没有时间限制),如果键一样则覆盖
  • 键值对有时间的限制,如果没有时间限制的话,就会一直保存在这个页面,默认值是表示在关闭浏览器是删除
  • 加盐时或者不加盐是取得键值对的值得方法有点不一样
  • resquest cookies是访问此网站是所传过来的
  • 本页面的cookies都会传给你你下个访问的页面

删除cookie:

rep=render(request,"buy.html")
rep.delete_cookie(xpg)
return rep

 登录检验的装饰器

from functools import wraps

def check_login(function):
@wraps(function)
def inner(request):
ret = request.COOKIES.get("xpg", None)
if ret == "mmd":
return function(request) #校验成功的函数
else:
return redirect("/login/")

return inner

 session

session的优点

session是存在服务端的,所以比较安全,而且可以储存的数据比较大。

session的相关的操作

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


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

# 会话session的key
request.session.session_key

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

# 检查会话session的key在数据库中是否存在
request.session.exists("session_key")

# 删除当前会话的所有Session数据,# 删除当前会话的所有Session数据,但是数据库里面没有,如果设置同样的键值对,其sessiondid会发生改变
request.session.delete()
  
# 删除当前的会话数据并删除会话的Cookie。
request.session.flush() 
    这用于确保前面的会话数据不可以再次被用户的浏览器访问
    例如,django.contrib.auth.logout() 函数中就会调用它。

# 设置会话Session和Cookie的超时时间
request.session.set_expiry(value)
    * 如果value是个整数,session会在些秒数后失效。
    * 如果value是个datatime或timedelta,session就会在这个时间后失效。
    * 如果value是0,用户关闭浏览器session就会失效。
    * 如果value是None,session会依赖全局session失效策略。

Session流程解析

技术图片

Session版登陆验证

技术图片
from functools import wraps


def check_login(func):
    @wraps(func)
    def inner(request, *args, **kwargs):
        next_url = request.get_full_path()
        if request.session.get("user"):
            return func(request, *args, **kwargs)
        else:
            return redirect("/login/?next={}".format(next_url))
    return inner


def login(request):
    if request.method == "POST":
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")

        if user == "alex" and pwd == "alex1234":
            # 设置session
            request.session["user"] = user
            # 获取跳到登陆页面之前的URL
            next_url = request.GET.get("next")
            # 如果有,就跳转回登陆之前的URL
            if next_url:
                return redirect(next_url)
            # 否则默认跳转到index页面
            else:
                return redirect("/index/")
    return render(request, "login.html")


@check_login
def logout(request):
    # 删除所有当前请求相关的session
    request.session.delete()
    return redirect("/login/")


@check_login
def index(request):
    current_user = request.session.get("user", None)
    return render(request, "index.html", {"user": current_user})
session登录验证

Django中的Session配置

Django中默认支持Session,其内部提供了5种类型的Session供开发者使用。

1. 数据库Session
SESSION_ENGINE = django.contrib.sessions.backends.db   # 引擎(默认)

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

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

4. 缓存+数据库
SESSION_ENGINE = django.contrib.sessions.backends.cached_db        # 引擎

5. 加密Cookie Session
SESSION_ENGINE = django.contrib.sessions.backends.signed_cookies   # 引擎

其他公用设置项:
SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
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,默认修改之后才保存(默认)

注意

  1. 在session默认是存在数据库里面的
  2. session在数据库里面的数据,如果超时的话一般需要request.session.clear_expired()来进行清除
  3. session比较的安全,在数据库里面可以查看的到,一般在Django.session里面可以看见的
  4. session是基于cookie的

CBV中加装饰器相关

CBV实现的登录视图

from django.views import View
class
LoginView(View): def get(self, request): """ 处理GET请求 """ return render(request, login.html) def post(self, request): """ 处理POST请求 """ user = request.POST.get(user) pwd = request.POST.get(pwd) if user == alex and pwd == "alex1234": next_url = request.GET.get("next") # 生成随机字符串 # 写浏览器cookie -> session_id: 随机字符串 # 写到服务端session: # { # "随机字符串": {user:alex} # } request.session[user] = user if next_url: return redirect(next_url) else: return redirect(/index/) return render(request, login.html)

要在CBV视图中使用我们上面的check_login装饰器,有以下三种方式:

from django.utils.decorators import method_decorator

1. 加在CBV视图的get或post方法上

from django.utils.decorators import method_decorator


class HomeView(View):

    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")
    
    @method_decorator(check_login)
    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

 

 check_login是检测登录的函数的名字

2. 加在dispatch方法上

from django.utils.decorators import method_decorator


class HomeView(View):

    @method_decorator(check_login)
    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

因为CBV中首先执行的就是dispatch方法,所以这么写相当于给get和post方法都加上了登录校验。

3. 直接加在视图类上,但method_decorator必须传 name 关键字参数

如果get方法和post方法都需要登录校验的话就写两个装饰器。

from django.utils.decorators import method_decorator

@method_decorator(check_login, name="get")
@method_decorator(check_login, name="post")
class HomeView(View):

    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

补充

CSRF Token相关装饰器在CBV只能加到dispatch方法上,或者加在视图类上然后name参数指定为dispatch方法。

备注:

  • csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
  • csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator


class HomeView(View):

    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

 

或者

from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator


@method_decorator(csrf_exempt, name=dispatch)
class HomeView(View):
   
    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

分页

见老师的博客

需要自己一步一步的弄懂,写好的在自己的桌面上。

 

 

 

 

 

.

以上是关于Cookie和Session的主要内容,如果未能解决你的问题,请参考以下文章

少部分手机浏览器对于COOKIE支持不够导致服务端无法读取session的解决方案

Cookie和Session的工作流程及区别(附代码案例)

cookie和session

cookie和session

cookie和session

会话技术知识点整理(Cookie和Session)