Django操作cookie,Django操作session,Django中的Session配置,CBV添加装饰器,中间件,csrf跨站请求

Django操作cookie

设置Cookie参数:

● key, 键
● value=’’, 值
● max_age=None, 超时时间 cookie需要延续的时间(以秒为单位)如果参数是\ None`` ,
这个cookie会延续到浏览器关闭为止
● expires=None, 超时时间(IE requires expires, so set it if hasn’t been already.)
● 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 ,
cookie只能由设置它的站点读取
● secure=False, 浏览器将通过HTTPS来回传cookie
● httponly=False 只能http协议传输,无法被JavaScript获取
(不是绝对,底层抓包可以获取到也可以被覆盖)


baidu.com------------->一级域名-------------->解析出来很多个二级域名
www.baidu.com  www1.baidu.com  www2.baidu.com  ly.baidu.com

# 买一个服务器的,有了IP----------》127.0.0.1/index/-------->hello.com----->域名解析
127.0.0.1  hello.com-----》DNS解析-----》127.0.0.1
secure=False, 浏览器将通过HTTPS来回传cookie
httponly=False 只能http协议传输,无法被JavaScript获取

获取cookie和设置cookie也可以通过js实现

# 前端如何设置cookie

# localstorage
# sessionStorage

清空cookie

def logout(request):
    rep = redirect("/login/")
    rep.delete_cookie("user")  # 删除用户浏览器上之前设置的usercookie值
    return rep
# 使用场景:退出登录(注销功能)

Django操作session

# session的数据是保存在后端,保存在后端的载体其实有很多种,比如:可以把数据保存在数据库、文件、Redis等

Django的默认保存位置在数据库中,在django_session表中,这张表是默认生成的

如何操作session
# 设置成功一个session值有什么变化
1. 会生成一个随机字符串
2. 会把用户设置的信息保存在django_session表中,数据也做了加密处理
3. 把数据封装到了request.session里去了
4. Django后端把随机字符串保存到了浏览器中
5. 随机字符串保存在浏览器中的key=sessionid

# 当设置多个session值的时候,session_key是不变的,变的是session_Data
# 当设置多个session值的时候,django_Session表中只存在一条记录(一台电脑的一个浏览器)

上述的做法有什么好处
节省MySQL的空间


# 获取session发生了哪些事?
1. 浏览器先把sessionid回传到Django的后端
2. Django后端获取到sessionid,然后去数据表中根据session_key查询
	# 如果查到了,说明之前已经登陆过了
    # 如果查不到,就返回None
3. 查询出来的数据默认是加密的,Django后端又把数据解密之后封装到request.session中
	# 在取session值的时候,就从request.session中取
    
# 设置过期时间
session的默认过期时间是14天
# 过期时间是可以更改的,如何更改...

Django中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(数据库和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中的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,默认修改之后才保存(默认)

CBV添加装饰器

from django.utils.decorators import method_decorator

# @method_decorator(login_auth, name='get')
# @method_decorator(login_auth, name='post')  # 第二种方式
class Login(View):
    # 第三种方式,重置dispatch
    @method_decorator(login_auth)
    def dispatch(self, request, *args, **kwargs):
        return super(Login, self).dispatch(request, *args, **kwargs)
    # 必须登录之后才能访问get访问
    # @method_decorator(login_auth)  # 第一种方式
    def get(self, request):
        return HttpResponse("get")

    # @method_decorator(login_auth) # # 第一种方式
    def post(self, request):
        return HttpResponse("post")

中间件

如果你想修改请求,例如被传送到view中的HttpRequest对象。
或者你想修改view返回的HttpResponse对象,这些都可以通过中间件来实现。

可能你还想在view执行之前做一些操作,这种情况就可以用 middleware来实现。

Django默认的中间件:(在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下图)

# 中间件它的执行位置在web服务网关接口之后,在路由匹配之前执行的
django中自带的有七个中间件
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',
]

# 每一个中间件都有它自己独立的功能
# 它也支持我们自己自定义中间件
只要是跟全局相关的都可以用中间件来实现
如何自定义中间件:
class SecurityMiddleware(MiddlewareMixin):
    def process_request(self, request):
        pass
    
    
    def process_response(self, request, response):
    	pass
    

class SessionMiddleware(MiddlewareMixin):
    def process_request(self, request):
        pass
     def process_response(self, request, response):
        psss
        
class CsrfViewMiddleware(MiddlewareMixin):
    def process_request(self, request):
        pass
    def process_response(self, request, response):
        pass
    
    
# 中间件就是一个类,然后这个类都继承了 MiddlewareMixin

# 这个类中有几个方法:
# 下面这两个必须要求掌握
process_request
process_response


process_view
process_template
process_exception

'''这几个方法并不是都要全写,而是,需要几个你就写几个!'''

自定义中间件步骤:
	1. 在项目名下或者任意的应用名下创建一个文件夹
    2. 在这个文件夹下面创建一个py文件
    3. 在该py文件中写一个自定义的类必须要继承MiddlewareMixin
    4. 写完之后紧接着一定要去配置文件中注册中间件
 


class MyMiddleware1(MiddlewareMixin):
    def process_request(self, request):
        # IP限制
        # 
        print("我是第一个自定义的中间件process_request")

    def process_response(self, request, response):
        print("我是第一个自定义中间件的process_response")
        return response  # 每一个process_response都必须有返回值response


class MyMiddleware2(MiddlewareMixin):
    def process_request(self, request):
        print("我是第二个自定义的中间件process_request")

    def process_response(self, request, response):
        print("我是第二个自定义中间件的process_response")
        return response  # 每一个process_response都必须有返回值response
    
# 研究:如果我在第一个中间件的process_request中return返回值,后续的中间件如何走?
它会执行同级别的process_response

流程图如下:

由此总结一下:

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

多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的,
也就是说第一个中间件的process_request方法首先执行,而它的process_response方法最后执行,
最后一个中间件的process_request方法最后一个执行,它的process_response方法是最先执行。

# Django里的中间件几乎是所有框架中写的最号的

csrf跨站请求

# 钓鱼网站

# 本质:form表单提交数据的问题
username
shenfenzheng
<input type='text' name='正规的'>

# 冒牌的
<input type='text' >

<input type='hidden' name='冒牌的'>

# 如何避免这种问题?

# 研究ajax发送post请求csrf验证

在form表单中应用:

<form action="" method="post">
    {% csrf_token %}
    <p>用户名:<input type="text" name="name"></p>
    <p>密码:<input type="text" name="password"></p>
    <p><input type="submit"></p>
</form>

在Ajax中应用:放在data里:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="/static/jquery-3.3.1.js"></script>
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    <p>用户名:<input type="text" name="name"></p>
    <p>密码:<input type="text" name="password" id="pwd"></p>
    <p><input type="submit"></p>
</form>
<button class="btn">点我</button>
</body>
<script>
    $(".btn").click(function () {
        $.ajax({
            url: '',
            type: 'post',
            data: {
                'name': $('[name="name"]').val(),
                'password': $("#pwd").val(),
                'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()
            },
            success: function (data) {
                console.log(data)
            }

        })
    })
</script>
</html>

使用django官方提供的js文件:

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');


// 每一次都这么写太麻烦了,可以使用$.ajaxSetup()方法为ajax请求统一设置。

function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

$.ajaxSetup({
  beforeSend: function (xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader("X-CSRFToken", csrftoken);
    }
  }
});

posted @ 2023-08-10 14:47  毓见  阅读(45)  评论(0)    收藏  举报