Day 13 cookie和session的使用
一、Cookie
Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。
cookie的由来
Http协议是无状态的,也就是每次请求都是独立的,他不会收到之前或者之后请求的影响,每次请求都是全新新的,cookie的产生就是为了状态保持,提取有用的数据,就像看到熟人一样。
cookie的原理
由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能通过Cookie的内容来判断这个是“谁”了
二、Django中操作Cookie
设置Cookie
rep
= HttpResponse
(...)
rep
= render
(request
, ...)
rep
.set_cookie
(key
, values
, ...)
rep
.set_signed_cookie
(key
, value
, salt
= '加密盐', max_age
=None, ...)
参数:
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获取(不是绝对,底层抓包可以获取到也可以被覆盖)
获取Cookie
request
.COOKIES
['key']
request
.get_signed_cookie
(key
, default
=RAISE_ESSOR
, salt
='', max_age
=None)
参数:
default: 默认值salt: 加密盐max_age: 后台控制过期时间
cookie的规范
-记住:当前网站在浏览器上cookie个数和大小有限制
-Cookie大小上限为4KB;
-一个服务器最多在客户端浏览器上保存
20个Cookie;
-一个浏览器最多保存
300个Cookie;
删除cookie
删除Cookie
def logout(request
):
rep
= redirect
("/login/")
rep
.delete_cookie
("user")
return rep
三、cookie版的登录校验
urls函数
urlpatterns
= [
url
(r
'^admin/', admin
.site
.urls
),
url
(r
'^signin/', views
.sign_in
),
url
(r
'^signout/', views
.sign_out
),
url
(r
'^order/', views
.order
),
url
(r
'^index/', views
.user_info
),
]
views视图函数
def login_auth(func
):
def wrapper(request
, *args
, **kwargs
):
name
= request
.COOKIES
.get
('name')
if name
:
result
= func
(request
, *args
, **kwargs
)
return result
else:
path
= request
.get_full_path
()
print(request
.get_full_path
())
return redirect
('/signin/?returnUrl=%s' % path
)
return wrapper
def sign_in(request
):
if request
.method
== 'POST':
name
= request
.POST
.get
('name')
password
= request
.POST
.get
('password')
if name
== 's' and password
== '123':
path
= request
.GET
.get
('returnUrl')
print(path
)
if path
:
obj
= redirect
(path
)
else:
obj
= redirect
('/index/')
obj
.set_cookie
('name', name
)
obj
.set_cookie
('password', password
)
return obj
else:
return HttpResponse
('账号或密码错误!')
return render
(request
, 'signin.html')
@login_auth
def sign_out(request
):
obj
= HttpResponse
('账号退出成功')
obj
.delete_cookie
('name')
obj
.delete_cookie
('password')
return obj
@login_auth
def order(request
):
return render
(request
, 'order.html')
@login_auth
def user_info(request
):
print(request
.COOKIES
)
return render
(request
, 'index.html')
html模板文件
# index
<div class="jumbotron">
<h1>用户信息
</h1>
<p>这是一个巨幕
</p>
<p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more
</a></p>
</div>
# oeder
<body>
<a href="/signout/">点我退出
</a>
</body>
# signin
<div class="col-md-4 col-md-offset-4">
<form action="" method="post">
<div class="form-group">
<label for="">账号
</label>
<input type="text" placeholder="账号" name="name">
</div>
<div class="form-group">
<label for="">密码
</label>
<input type="password" placeholder="密码" name="password">
</div>
<input type="submit" class="btn btn-info text-center" value="注册">
</form>
</div>
四 django中session的使用
Session的由来
Cookie虽然在一定程度上解决了“保持状态”的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是Session。
总结而言:Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是Cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。
另外,上述所说的Cookie和Session其实是共通性的东西,不限于语言和框架。
Django中Session相关用法
def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
domain=None, secure=False, httponly=False)
参数
keyvaluemax_age:传个数字,以秒计,过期时间,有默认值 (6天后过期:606024*5)—了解expires:传时间对象,date=datetime.timedelta()path:默认 / 表示当前域下的所有路径 http://127.0.0.1:8000/lqz/dfd/domain:在那个域下有效secure:是否Https传输cookiehttponly:cookie只支持http传输
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
()
request
.session
.session_key
request
.session
.clear_expired
()
request
.session
.exists
("session_key")
request
.session
.delete
()
request
.session
.flush
()
这用于确保前面的会话数据不可以再次被用户的浏览器访问
例如,django
.contrib
.auth
.logout
() 函数中就会调用它。
request
.session
.set_expiry
(value
)
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是
0,用户关闭浏览器session就会失效。
* 如果value是
None,session会依赖全局session失效策略。
Django中的Session配置
Django中默认支持Session,其内部提供了5种类型的Session供开发者使用。
1. 数据库Session
SESSION_ENGINE
= 'django.contrib.sessions.backends.db'
2. 缓存Session
SESSION_ENGINE
= 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS
= 'default'
3. 文件Session
SESSION_ENGINE
= 'django.contrib.sessions.backends.file'
SESSION_FILE_PATH
= None
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_PATH =
"/"
SESSION_COOKIE_DOMAIN
= None
SESSION_COOKIE_SECURE
= False
SESSION_COOKIE_HTTPONLY
= True
SESSION_COOKIE_AGE
= 1209600
SESSION_EXPIRE_AT_BROWSER_CLOSE
= False
SESSION_SAVE_EVERY_REQUEST
= False
五、CBV(基于类的视图)加装饰器
视图函数
class LoginView(View
):
def get(self
, request
):
"""
处理GET请求
"""
return render
(request
, 'signin.html')
def post(self
, request
):
"""
处理POST请求
"""
user
= request
.POST
.get
('user')
pwd
= request
.POST
.get
('pwd')
if user
== 'alex' and pwd
== "alex1234":
next_url
= request
.GET
.get
("next")
request
.session
['user'] = user
if next_url
:
return redirect
(next_url
)
else:
return redirect
('/index/')
return render
(request
, 'signin.html')
要在CBV视图中使用我们上面的check_login装饰器,有以下三种方式:
from django.utils.decorators import method_decorator
方法一、加在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/")
方法二、加在dispatch方法上
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/")
因为CBV中首先执行的就是dispatch方法,所以这么写相当于给get和post方法都加上了登录校验。
方法三、直接加在视图类上,但method_decorator必须传 name 关键字参数
如果get方法和post方法都需要登录校验的话就写两个装饰器。
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/")
补充
CSRF Token相关装饰器在CBV只能加到dispatch方法上,或者加在视图类上然后name参数指定为dispatch方法。
备注:
csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
方法一
from django
.views
.decorators
.csrf
import csrf_exempt
, csrf_protect
from django
.utils
.decorators
import method_decorator
class HomeView(View
):
@method_decorator
(csrf_exempt
)
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/")
方法二
from django
.views
.decorators
.csrf
import csrf_exempt
, csrf_protect
from django
.utils
.decorators
import method_decorator
@method_decorator
(csrf_exempt
, name
='dispatch')
class HomeView(View
):