django中的Session

it2023-02-07  48

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) # token = get_token(user.id) # res = JsonResponse({ # "user":jsonify(user,exclude={"password"}), # "token":token # },status=201) # res.set_cookie(settings.TOKEN,token) from django.contrib.sessions.backends.db import SessionStore #持久的session session:SessionStore = request.session print(session,type(session)) print(session.keys()) session.set_expiry(300) #设置session会话过期时间300秒 session["user_id"] = user.id # session["user_info"] = "<{} {} {}>".format(user.id,user.name,user.email) #会存储在服务端,数据库中 uobj = jsonify(user,exclude=["password"]) session["user_info"] = uobj # u = session["user_info"] # print(u) # print("-"*30) res = JsonResponse({ "user":uobj },status=201) return res except Exception as e: logging.info(e) return JsonResponse({ "error": XddError.USERPW_ERROR },status=404) # 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 # # 从请求cooker中获取token # token = request.META.get(settings.HTTP_TOKEN) # if not token: # logging.info("身份认证失败") # return HttpResponse(status=401) # # 验证 # id = jwt.decode(token,settings.SECRET_KEY,alogorithms=[settings.JWT_ARITHMETIC])["user_id"] from django.contrib.sessions.backends.db import SessionStore # 持久的session session:SessionStore = request.session id = session["user_id"] #如果获取失败,说明session过期,或没有 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 #配置url路由 @authenticate #在有需要的视图函数上加上装饰器 #没有登录过,就不用登出了,所以要认证 def logout(request:HttpRequest): info = "{} logout.".format(request.session["user_id"]) del request.session["user_id"] # 不会清除数据库中记录 request.session.flush() # 情况当前session,删除表中对应记录 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): #视图函数,需要配置url映射 if request.session.get("user_id"): #访问Session字典中的值 print(request.session.items()) return HttpResponse("test1 ok") else: return HttpResponseBadRequest() #没有此信息,说明没有登录成功过
最新回复(0)