Day 58 cookie与session/django中间件

[TOC]html

cookie

cookie产生的缘由是由于HTTP协议是无状态的前端

无状态的意思就是每次请求都是独立的,它的执行状况和结果与前面的请求和以后的请求都无直接关系,它不会受前面的请求响应状况直接影响,也不会直接影响后面的请求响应状况python

状态能够理解为客户端和服务器在某次会话中产生的数据,那无状态的就觉得这些数据不会被保留.会话中产生的数据又是咱们须要保存的,也就是说要保持状态.所以Cookie就是在这样一个场景下诞生的数据库

什么是cookie

cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,一边服务器提取有用信息django

cookie的原理

cookie的工做原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能经过cookie的内容来判断这个是"谁"了浏览器

Django中操做Cookies

设置Cookie

def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'tiny' and password == '123':
            # 固定登录成功后跳转的页面
            old_path = request.GET.get('next')
            if old_path:
                obj = redirect(old_path)
            else:
                obj = render(request, 'home.html')
            # 设置cookie值
            obj.set_cookie('user_info', username)
            return obj
        return HttpResponse('密码错误')

获取cookie

def login_auth(func):
    def inner(request, *args, **kwargs):
        # 获取cookie
        if request.COOKIES.get('user_info'):
            res = func(request, *args, **kwargs)
            return res
        else:
            target_path = request.path_info
            return redirect('/login/?next=%s' % target_path)
    return inner

删除cookie

def logout(request):
    rep = redirect('/home/')
    rep.delete_cookie('user_info')
    return rep

session

Cookie虽然在必定程度上解决了“保持状态”的需求,可是因为Cookie自己最大支持4096字节,以及Cookie自己保存在客户端,可能被拦截或窃取,所以就须要有一种新的东西,它能支持更多的字节,而且他保存在服务器,有较高的安全性。这就是Session。安全

问题来了,基于HTTP协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的Cookie就起到桥接的做用。服务器

咱们能够给每一个客户端的Cookie分配一个惟一的id,这样用户在访问时,经过Cookie,服务器就知道来的人是“谁”。而后咱们再根据不一样的Cookie的id,在服务器上保存一段时间的私密资料,如“帐号密码”等等。cookie

总结而言:Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;可是Cookie以文本的形式保存在本地,自身安全性较差;因此咱们就经过Cookie识别不一样的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。session

另外,上述所说的Cookie和Session实际上是共通性的东西,不限于语言和框架。

Django中操做Session

设置session

class MyLogin(View):
    def get(self, request):
        return render(request, 'login.html')

    def post(self, request):
        username = request.POST.get('name')
        pwd = request.POST.get('pwd')
        # print(pwd, type(pwd))
        data = models.User.objects.filter(username=username)
        user_obj = data[0]
        if not user_obj:
            return HttpResponse('当前用户不存在!')
        if user_obj.pwd == pwd:
            old_path = request.GET.get('next')
            if old_path:
                obj = redirect(old_path)
            else:
                obj = render(request, 'home.html')
            # 设置session值
            request.session['user_info'] = username
            return obj
        return render(request, 'login.html', {'msg': '密码错误'})

获取session

def login_auth(func):
    def inner(request, *args, **kwargs):
        # 获取session
        if request.session.get('user_info'):
            res = func(request, *args, **kwargs)
            return res
        else:
            target_path = request.path_info
            return redirect('/login/?next=%s' % target_path)
    return inner

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数据
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失效策略。

Django中间件

中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量,低级别的插件系统,用于在全局范围内改变Django的输入和输出.梅哥中间件组件都负责作一些特定的功能

可是因为其影响的是全局,因此须要谨慎使用,使用不当会影响性能

说的直白一点中间件是帮助咱们在视图函数执行以前和执行以后均可以作一些额外的操做,它本质就是一个自定义类,类中定义了几个方法,Django框架会在请求的特定的时间去执行这些方法

咱们一直都在使用中间件,只是没注意到而已,打开Django项目的Settings.py文件

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

自定义中间件

中间件能够定义五个方法,分别是:

须要掌握:

  • process_request(self, request)
  • process_response(request)

须要了解

  • process_view(self, request, view_func, view_args, view_kwargs)
  • process_exception(self, request, exception)
  • process_template_response(self, request, response)

以上方法的返回值能够是None或者一个HttpResponse对象,若是是None,则继续按照Django定义的规则向后继续执行,若是是HttpResponse对象,则直接将该对象返回用户

process_request

总结:

  1. 中间件的process_request方法是在执行视图函数以前执行的
  2. 当配置多个中间件时,会按照MIDDLEWARE中的注册顺序,也就是列表的索引值,从前到后依次执行的
  3. 不一样中间件之间传递的request都是同一个对象

process_response

总结:

  1. 多个中间中的process_response方法是安装MIDDLEWARE的注册顺序倒序执行的
  2. 该方法必须有两个参数,而且必须返回response形参,不返回直接报错
  3. 该方法返回什么HttpResponse对象,前端就能得到什么

process_view

  1. 路由匹配成功以后执行视图函数以前触发
  2. 若是该方法返回了HttpResponse对象,那么会从下往上通过每个中间件里面的process_response方法

process_template_response

当你返回对象中含有render属性指向的是一个render方法的时候才会触发,从上往下的顺序

def mdzz(request):
    print('我是视图函数mdzz')
    def render():
        return HttpResponse('你好呀 我是奇葩')
    obj = HttpResponse('我很好 好的像个傻逼同样')
    obj.render = render
    return obj

process_exception

当视图函数中出现错误时,会自动触发,顺序是从上往下

相关文章
相关标签/搜索