django中的Session
Session-Cookie机制
网景公司发明了Cookie技术,为了解决浏览器端数据存储问题。
每一次request请求时,会把此域名相关的Cookie发往服务器端。服务器端也可以使用response中的set-cookie来 设置cookie值。 动态网页技术,也需要知道用户身份,但是HTTP是无状态协议,无法知道。必须提出一种技术,让客户端提交的信息可以表明身份,而且不能更改。这就是Session技术。Session开启后,会为浏览器端设置一个Coolie值,即SessionID.这个放置SessionID的Cookie是会话级的,浏览器不做持久化存储只放在内存中,并且浏览器关闭自动清除。浏览器端发起一个HTTP请求后,这个SessionID会通过Cookie发到服务器端,服务端就可以通过这个ID查到对应的一个字典结构。如果查无此ID,就为此浏览器重新生成一个SessionID,为它建立一个SessionID和空字典的映射关系。可以在这个ID对应的Session字典中,存入键值对来保持与当前会话相关的信息。
Session会定期过期清除Session占用服务端内存Session如果没有持久化,如果服务程序崩溃,那么所有Session信息丢失Session可以持久化到数据库中,如果服务程序崩溃,那么可以从数据库中恢复
开启session支持
Django可以使用Session
在settings中,MIDDLEWARE设置中,启用django.contrib.sessions.middleware.SessionMiddleware。在INSTALLED_APPS设置中,启用django.contrib.sessions。它是基于数据库存储的Session。Session不使用,可以关闭上述配置,以减少开销在数据库的表中的django_session表,记录session信息。但可以使用文件系统或其他cache来存储
登录登出实现
登录实现
原来登录成功,会使用jwt的token发往客户端。现在不需要了,只需要在Session中记录登录信息即可。(Django默认请求session会持久化数据库中的django_session表中)
def jsonify(obj
,allow
=None,exclude
=set()):
"""# 筛选对象中的属性,allow白名单,exclude黑名单"""
if allow
:
allow
= set(map(lambda x
: str.lower
(x
), allow
))
fn
= lambda x
: x
.name
.lower
() in allow
else:
exclude
= set(map(lambda x
: str.lower
(x
), exclude
))
fn
= lambda x
: x
.name
.lower
() not in exclude
names
= type(obj
)._meta
.fields
return {i
.name
:getattr(obj
,i
.name
) for i
in filter(fn
,names
)}
@require_POST
def login(request
:HttpRequest
):
try:
palyload
= simplejson
.loads
(request
.body
)
email
= palyload
["email"]
password
= palyload
["password"].encode
()
name
= palyload
["name"]
user
= User
.objects
.get
(email
=email
)
if not bcrypt
.checkpw
(password
,user
.password
.encode
()):
return JsonResponse
({"error": XddError
.USERPW_ERROR
},404)
from django
.contrib
.sessions
.backends
.db
import SessionStore
session
:SessionStore
= request
.session
print(session
,type(session
))
print(session
.keys
())
session
.set_expiry
(300)
session
["user_id"] = user
.id
uobj
= jsonify
(user
,exclude
=["password"])
session
["user_info"] = uobj
res
= JsonResponse
({
"user":uobj
},status
=201)
return res
except Exception
as e
:
logging
.info
(e
)
return JsonResponse
({
"error": XddError
.USERPW_ERROR
},status
=404)
登录成功,浏览器端,就能收到一条set-Cookie
sessionid
=hjg0j01pbvadxdjd5jf9pn91larvv10t
; path
=/; domain
=localhost
; HttpOnly
; Expires
=Wed
, 24 Jul
2019 13:19:01 GMT;
session.set_expiry(300)方法。设置session过期时间
300秒过期None表示使用全局session过期策略0表示会话级session,即浏览器关闭过期datetime对象表示在指定时间点过期 建议不要再Session中保存太多数据,也不要保存过于复杂的类型。
认证实现
取消原有判断HTTP hander中是否提供了JWT信息,改为判断该SessionID是否能找到一个字典,这个字典中是否有登录成功后设置的user_id键值对信息。
def authenticate(fn
):
def _wapper(*args
,**kwargs
):
try:
*_
,request
= args
from django
.contrib
.sessions
.backends
.db
import SessionStore
session
:SessionStore
= request
.session
id = session
["user_id"]
user
= User
.objects
.get
(id=id)
request
.user
= user
res
= fn
(*args
, **kwargs
)
return res
except Exception
as e
:
logging
.info
(e
)
return JsonResponse
({"error":XddError
.LOGIN_OUT_TIME
},status
=401)
return _wapper
登录代码
@require_POST
@authenticate
def logout(request
:HttpRequest
):
info
= "{} logout.".format(request
.session
["user_id"])
del request
.session
["user_id"]
request
.session
.flush
()
return JsonResponse
({},status
=200)
登出时,需要调用flush方法,清除session,清除数据库记录。
登录成功,为当前session在django_session表中增加一条记录,如果没有登出操作,那么该记录不会消失。Django也没有自动清除记录的功能。但是Django提供了一个命令clearsessions,建议在cron中定期执行。
django-admin.py clearsessions
manage.py clearsessions
不需要认证的view函数中使用Session
在当前会话中,每次request请求中都会得到浏览器端发出的SessionID,因此都可以在服务器端找到该ID对应的Session字典,可以使用request.session访问。所有请求都可以使用request.session对象,ID找不到可以认为返回个空字典。
def test1(request
):
if request
.session
.get
("user_id"):
print(request
.session
.items
())
return HttpResponse
("test1 ok")
else:
return HttpResponseBadRequest
()