加载中...

Cookie和Session

Cookie大小上限为4KB;
一个服务器最多在客户端浏览器上保存20个Cookie;
一个浏览器最多保存300个Cookie,因为一个浏览器可以访问多个服务器。
cookie设置的数据是明文存储在客户端的,不安全

为了维护登录状态

Http协议

无状态: 不会记录任何客户端和服务端的信息

无连接(closed)(短连接(keepalive)): 一次请求一次响应,就断开连接了.

1606874306656

会话

http协议不能为之会话

cookie 后端服务端给cookie中设置的令牌,键值对形式设置

cookie是浏览器技术,针对的就是http协议无状态,导致不能和服务端维持会话,例子:登录,登录之后,看到响应结果,继续访问其他有页面,服务端要判断

Cookie过程

1606875435700

1606876228911

下次请求自动携带cookie

16068779031251606876411379

网址1: {xx:oo,xx1:oo1}
网址2: {xx:oo,xx1:oo1}
网址3: {xx:oo,xx1:oo1}

每次请求对应网址时,都会自动携带这个网址对应的cookie数据,放到http请求头部信息中.

Cookie在Django中

# 设置cookie(包含添加和修改),键相同时是修改
rep = HttpResponse(...)
rep = render(request, ...)
rep.set_cookie(key,value,...)

# 获取cookie
request.COOKIES  # 是字典
# 获取字段
request.COOKIES['key']
request.COOKIES.get('key')


# 删除cookie
def logout(request):
	ret = redirect('login')
	ret.delete_cookie('is_login')

	return ret


# set_cookie的一些参数
	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获取(不是绝对,底层抓包可以获取到也可以被覆盖)

Session

数据存储到了服务端

大小无限制

并且表面上比cookie安全一些,最起码不是铭文的.

1606880611836

1606880762310

Django的Session中

#取值
request.session['k1'] 
request.session.get('k1',None) # get方法不报错

# s设置值 (新增和修改)
request.session['k1'] = 123  #键相同的还是修改
request.session.setdefault('k1',123)

# 删除

# 删除单个数据:
    #删除值
	del request.session['k1']
# 删除所有数据
	request.session.flush()
session配置
方法
# 设置会话Session和Cookie的超时时间
request.session.set_expiry(value)
    * 如果value是个整数,session会在些秒数后失效。
    * 如果value是个datatime或timedelta,session就会在这个时间后失效。
    * 如果value是0,用户关闭浏览器session就会失效。
    * 如果value是None,session会依赖全局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,默认修改之后才保存(默认)

认证器

# 登录认证装饰器
def login_check(f):

    def inner(request, *args, **kwargs):
       status = request.session.get('is_login')
       if status == True:
          ret = f(request, *args, **kwargs)
          return ret
       else:
          return redirect('login')
    return inner

CSRF和Token

详述CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。攻击者通过HTTP请求江数据传送到服务器,从而盗取回话的cookie。盗取回话cookie之后,攻击者不仅可以获取用户的信息,还可以修改该cookie关联的账户信息。

1606968635000

img

Token的认证方式

token字符串的前32位是salt, 后面是加密后的token, 通过salt能解密出唯一的secret。
django会验证表单中的token和cookie中token是否能解出同样的secret,secret一样则本次请求合法。

1 在响应的页面中加入{% csrf_token %}标签,那么在进行模板渲染是会生成如下标签
	<input type="hidden" name="csrfmiddlewaretoken" value="ppwN8yg1wVEyXDxtMpVIrc4zV3gHiDKKb9rwGPLaSGRc0HKhXAwpNrKjGDUHIxjj">

2 并且在响应还有这个	{% csrf_token %}标签的页面时,会添加cookie键值对,如下
#  csrftoken:lsMQeJgVbIKKxlfz6umgYM8WOWx1Njr77cHzM0L4xtXoApsnhFXXk1OGzwb1dd0G	

3 当用户从该页面提交数据时,会携带csrfmiddlewaretoken:ppwN8yg1wVEyXDxtMpVIrc4zV3gHiDKKb9rwGPLaSGRc0HKhXAwpNrKjGDUHIxjj和cookie键值对

4 取出cookie中的csrftoken值和请求数据部分的csrfmiddlewaretoken的值,两者进行比较,这个随机字符串叫做token字符串. django如果在请求数据部分找不到tokne值,会去请求数据中的请求行部分,找一个叫做X-CSRFToken的键值对,如果这个键对应的值和cookie中csrftoken对应的值相同,也能通过认证.
	过程:
    	token字符串的前32位是salt, 后面是加密后的token, 通过salt能解密出唯一的secret字符串。
        secret:是settings配置文件中的serect_key:
              SECRET_KEY = 's!xbzez1zxrevmq7k_89%%-z&#)e7686pyq8pg@_bp_k_2s^ho'
		django会验证表单中的token和cookie中token是否能解出同样的secret,secret一样则本次请求合法。
		如果不同就403 forbidden

Django中设置Token

{% csrf_token %}

Ajax设置Cookie

 html中:
   	 {% csrf_token %}
    
    $('#btn').click(function () {

        var uname = $("#username").val();
        var password = $("#password").val();
        var token = $("[name='csrfmiddlewaretoken']").val();  // 读取 input的cookie值


        $.ajax({
            type: 'post',  // 请求方法.
            url: '/login/',

            data: {xname: uname, pwd: password, csrfmiddlewaretoken: token}, // key固定
            success: function (res) {
                console.log('success', res);

            },
            error: function (error) {
                console.log('error>>>>>', error);
                $('#ajax_error').text(error.responseText);

            }

        })

    })
    
      
 方式2
	$.ajax({
            type: 'post',  // 请求方法.
            url: '/login/',
            // {{ csrf_token }}拿到是{% csrf_token %}生成的input标签的那个value属性的token值
            data: {xname: uname, pwd: password, csrfmiddlewaretoken: '{{ csrf_token }}'},
            success: function (res) {
                console.log('success', res);

            },
            error: function (error) {
                console.log('error>>>>>', error);
                $('#ajax_error').text(error.responseText);

            }

        })

      
   方式3 添加请求头键值对,键必须叫做:'X-CSRFToken',值是cookie中的token值
	$.ajax({
            type: 'post',  // 请求方法.
            url: '/login/',

            data: {xname: uname, pwd: password},
            headers:{  // 设置请求头键值对
                'X-CSRFToken':$.cookie('csrftoken'),
            },
            success: function (res) {

                console.log('success', res);

            },
            error: function (error) {
                console.log('error>>>>>', error);
                $('#ajax_error').text(error.responseText);

            }
        })

上传文件

form表单上传文件

<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    用户名: <input type="text" name="username">
    密码: <input type="password" name="password">
{#    头像: <input type="file" name="avatar" multiple>#}
    头像: <input type="file" name="avatar">
    <input type="submit">

</form>

views

def upload(request):

	if request.method == 'GET':
		return render(request, 'upload.html')
	else:
		print(request.POST)  #如果没有修改请求消息格式(content-type),那么文件名称会在request.POST中拿到,但是只是文件名称
		print(request.FILES) # 里面放的是文件数据(文件对象,类似于文件句柄)
		# print(request.FILES.getlist('avatar'))
		# print(request.FILES.get('avatar'))  # timg.jpg
		file_obj = request.FILES.get('avatar')
		print(file_obj.name)  #文件名称

		with open(file_obj.name, 'wb') as f:
			# for i in file_obj:
			# 	f.write(i)
			for i in file_obj.chunks():
				#默认一次返回大小为经测试为65536B,也就是64KB,最大为2.5M,是一个生成器
				f.write(i)


		return HttpResponse('ok')

ajax上传文件

$("#sub").click(function (){
        var uname = $('[name="username"]').val();
        var pwd = $('[name="password"]').val();
        var file_obj = $('[type="file"]')[0].files[0];

        // ajax上文件,必须将文件数据放到一个叫做formdata的对象中才能发送
        var formdata = new FormData();
        formdata.append('username',uname)
        formdata.append('password',pwd)
        formdata.append('csrfmiddlewaretoken', '{{ csrf_token }}')
        formdata.append('avatar',file_obj)  // requser.FILES.get('avatar')

        $.ajax({
            url:'/upload/',
            type:'post',
            data:formdata,  // ajax会将本次请求的数据格式改为 content-type: multipart/form-data

            // 告诉ajax不要对数据进行预处理和加工,向上传文件必须加上这两个参数
            contentType:false,
            processData: false,

            success:function (res){

            }

        })

    });

posted @ 2024-05-09 22:10  江寒雨  阅读(46)  评论(0)    收藏  举报