Django 之cookie和session

1、cookie 介绍

  由来:主要是HTTP协议是无状态的链接,意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况。所以当客户端和服务端在某次会话中产生的数据是我们需要保存下的,这时就需要一个容器,这个容器就是cookie。

  什么是cookie:cookie 是一个容器,保存在浏览器上key-value结构数据。

  原理:由服务器创建,放在响应消息的响应头内发给给浏览器,浏览器会把cookie保存下来,当下次在访问服务器时把cookie随请求信息发送给服务器,服务器验证cookie,就可以知道客户端当前的状态。

  浏览器中查看:

  浏览器清除cookie:设置里,在清除浏览数据中,可以清除Cookie

2、Django中操作Cookie

  2.1 设置cookie

# 一般使用:
rep = render(request, ...)
rep = HttpRsponse(...)

rep.set_cookie(key, value)
rep.set_signed_cookie(key, value, salt="加密盐",...)

return rep
       
# cookie 一些参数:

set_cookie(self, key, value, max_age, expires, path, domain, secure, httponly)

# key, value:表示的键和值
# max_age: 超时时间, cookie需要延续的时间(单位: 秒)参数"None", 表示cookie会延续到浏览器关闭为止
# expires=None, 超时时间,在IE浏览器上需要设置,格式:时间格式的字符串,或datatime类型时间
# path='/', Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被根路径下的任何url的页面访问,浏览器只会把cookie回传给带有该路径的页面,这样可以避免将cookie传给站点中的其他的应用
# domain=None, Cookie生效的域名 你可用这个参数来构造一个跨站cookie。如, domain=".example.com"所构造的cookie对下面这些站点都是可读的:www.example.com 、 www2.example.com 和an.other.sub.domain.example.com。None表示只能由设置它的站点读取。
# secure=False, 浏览器将通过HTTPS来回传cookie
# httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

set_signed_cookie(self, key, value, salt='', **kwargs)

# 参数:salt:自定义加密类型,可以是任意字符
# 如果使用set_signed_cookie("login", "true", salt="aaa"),
# 则取cookie时get_signed_cookie("login", salt="aaa")

# 底层调用的set_cookie()
def set_signed_cookie(self, key, value, salt='', **kwargs):
    value = signing.get_cookie_signer(salt=key + salt).sign(value)
    return self.set_cookie(key, value, **kwargs)

  2.2 获取cookie

request.COOKIES['key']
reuqest.COOKIES.get("key")
request.get_signed_cookie(key, salt='', max_age=None, default=None)
# default: 当找不到cookie时返回的值,

  2.3 删除Cookie

rep.delete_cookie("key")  # 删除浏览器之前设置的cookie

  2.4 Cookie 登录验证

# 使用了装饰器

from functools import wraps
def check_login(func):
    @wraps(func)
    def inner(request, *args, **kwargs):
        next_url = request.get_full_path()
        if request.get_signed_cookie("login", salt="2019-4-24", default=None) == "true":
            # 已经登录的用户...
            return func(request, *args, **kwargs)
        else:
            # 没有登录的用户,跳转刚到登录页面
            return redirect("/login/?returnURL={}".format(next_url))
    return inner

def login(request):
    # 先判断是否已经登录过
    if request.get_signed_cookie("login", salt="2019-4-24", default=None) == "true":
        return HttpResponse("已登录")

    if request.method == "POST":
        name = request.POST.get("name")
        pwd = request.POST.get("pwd")
        if name == "sun" and pwd == "123":
            next_url = request.GET.get("returnURL", "")
            next_url = next_url if next_url else "/home/"
            response = redirect(next_url)
            response.set_signed_cookie("login", "true", salt="2019-4-24")
            return response
    return render(request, "login.html")

@check_login
def index(request):
    """只有登录后才能查看"""
    return HttpResponse("This is index....")

@check_login
def home(request):
    """只有登录后才能查看"""
    return HttpResponse("This is home....")
使用Cookie登录验证

3、session 介绍

  由来:虽然Cookie你不了HTTP无状态的不足,但是它是以文本的形式保存在本地,自身安全性差,容易被他人获取,这是就有了session。

  什么是session:一个容器,保存在服务端的key-value结构的数据。

  原理:由服务器创建,key为服务器生成的随机字符串,然后把key放到cookie中({"sessionid": key})随响应信息发送个客户端,当客户端下次访问时把cookie发送给服务端,服务端就可以通过session得到用户状态。

4、django 使用session

  在使用前一定先在命令行执行数据库迁移命令

  4.1 session 的方法

可以使用字典的方法操作session

# 设置 session
request.session[key] = value
request.session.setdefault(key, value)

# 设置的过程 
# 1.内部自动生成一个随机字符串   一个浏览器对应一个
# 2.将随机字符串与数据字典存入django session表中
# 3.将随机字符串设置到浏览器的cookie中

# 获取 session
request.session['k1']
request.session.get('k1',None)(推荐)

# 删除
del request.session['k1']

# 获取键,值,键值对
request.session.keys()
request.session.values()
request.session.items()

# 会话session的key
request.session.session_key  # 随机字符串


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


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


# 删除当前会话的所有Session数据
request.session.delete()    # 只删django_session表里的数据

  
# 删除当前的会话数据并删除会话的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失效策略。

  4.2 django中session配置

# settings.py 文件下

#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,默认修改之后才保存(默认)

  4.3 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("login") == "true":
            # 已经登录的用户...
            return func(request, *args, **kwargs)
        else:
            # 没有登录的用户,跳转刚到登录页面
            return redirect("/login/?returnURL={}".format(next_url))
    return inner

def login(request):
    # 先判断是否已经登录过
    if request.session.get("login") == "true":
        return HttpResponse("已登录")
    if request.method == "POST":
        name = request.POST.get("name")
        pwd = request.POST.get("pwd")
        if name == "sun" and pwd == "123":
            # 设置session
            request.session["login"] = "true"
            next_url = request.GET.get("returnURL", "")
            next_url = next_url if next_url else "/home/"
            response = redirect(next_url)
            return response
    return render(request, "login.html")

@check_login
def index(request):
    """只有登录后才能查看"""
    return HttpResponse("This is index....")

@check_login
def home(request):
    """只有登录后才能查看"""
    return HttpResponse("This is home....")
使用session实现登录验证

  4.4 CBV 实现登录视图

# 登录函数和装饰器

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("login") == "true":
            # 已经登录的用户...
            return func(request, *args, **kwargs)
        else:
            # 没有登录的用户,跳转刚到登录页面
            return redirect("/login/?returnURL={}".format(next_url))
    return inner


def login(request):
    # 先判断是否已经登录过
    if request.session.get("login") == "true":
        return HttpResponse("已登录")
    if request.method == "POST":
        name = request.POST.get("name")
        pwd = request.POST.get("pwd")
        if name == "sun" and pwd == "123":
            # 设置session
            request.session["login"] = "true"
            next_url = request.GET.get("returnURL", "")
            next_url = next_url if next_url else "/home/"
            response = redirect(next_url)
            return response
    return render(request, "login.html")

  4.5 对于CBV上得装饰器用法

    使用django自带添加装饰器的方法

      from django.utils.decorators import method_decorator

    1. 方式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/")

    2. 方式2:放在dispatch方法上

# 因为CBV首先执行的dispatch函数,所以这样写就相当于给get和post都加上了登录校验

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/")

    3. 方式3:直接放到类上,但method_decorator必须要传name关键字参数

# 给post和get都加上登录校验

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/")

 

posted @ 2019-04-30 20:58  yw_sun  阅读(190)  评论(1)    收藏  举报