Cookie和Session
Cookie
Cookie大小上限为4KB;
一个服务器最多在客户端浏览器上保存20个Cookie;
一个浏览器最多保存300个Cookie,因为一个浏览器可以访问多个服务器。
cookie设置的数据是明文存储在客户端的,不安全
为了维护登录状态
Http协议
无状态: 不会记录任何客户端和服务端的信息
无连接(closed)(短连接(keepalive)): 一次请求一次响应,就断开连接了.

会话
http协议不能为之会话
cookie 后端服务端给cookie中设置的令牌,键值对形式设置
cookie是浏览器技术,针对的就是http协议无状态,导致不能和服务端维持会话,例子:登录,登录之后,看到响应结果,继续访问其他有页面,服务端要判断
Cookie过程


下次请求自动携带cookie


网址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安全一些,最起码不是铭文的.


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关联的账户信息。
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){
}
})
});

浙公网安备 33010602011771号