热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Django中的Session和cookie

Session和cookie参考文献:https:www.cnblogs.comwupeiqiarticles5246483.html1.问题引入1.1cookie是什么?保存在客

Session和COOKIE



  • 参考文献:https://www.cnblogs.com/wupeiqi/articles/5246483.html


1.问题引入


1.1 COOKIE是什么?



  • 保存在客户端浏览器上的键值对


1.2 Sessions



  • 保存在服务端的数据(本质上是键值对)



    • 应用:依赖COOKIE



    • 作用:保持会话(web网站)



    • 好处:敏感信息不会直接给客户端





  • image-20220105095100288




1.3 简单示例




  • image-20220105100844552

  • image-20220105102452687




2.COOKIE



  • COOKIE进行维持会话,一个浏览器只能存储20个COOKIE,服务端上限为300COOKIE



    • 注意:COOKIE大小不能超过4kb



  • COOKIE一般不会设置中文



# 中文COOKIE的设置一般有两种方式
# 1、使用decode('iso-8859-1').encode('utf-8')的方式
# 字符串不能直接使用decode因此,注意使用顺序
# 2、使用json,进行序列化,返回的方式为unique编码的字符串

2.1 简单应用



  • 登录界面设置COOKIE防止其他非登录界面的人员进行访问

from django.shortcuts import render,redirect,HttpResponse
# Create your views here.
def index(request):
if request.COOKIES.get('is_login')=='True':
return render(request,'index.html')
else:
return HttpResponse('你没成功!')
def login(request):
if request.method=='GET':
return render(request,'login.html')
if request.method=='POST':
username=request.POST.get('username')
pwd=request.POST.get('pwd')
if username=='aaa' and pwd=='666':
ret=redirect('index')
# 设置COOKIE的键值对
ret.set_COOKIE('is_login',True)
print('访问成功')
return ret
else:
return redirect('login')


  • 注意:COOKIE虽然可以实现登录的验证,但是会将状态设置在客户端浏览器,因此并不安全。


2.2 COOKIE的分发与验证



  • 使用装饰器进行封装COOKIE的分发与验证




  • 装饰器的简单复习


#编写装饰器
def wapper(f):
#装饰器的参数f为引用@下面的相关函数
def inner(request,*args,**kwargs):
# 决定执行先后的分界线
ret=f(*args,**kwargs)

return ret
return inner
# 调用装饰器
@wapper
def test():
pass
'''
知识点
函数内部定义一个函数,该函数要调用一下原函数的参数
最外层函数的返回值为内层函数
装饰器的调用
@name
*************
装饰器与Python 的闭包相关联,且知识点与js的函数参数可以为函数高度相似
'''



  • 装饰器的COOKIE


from django.shortcuts import render,redirect,HttpResponse
# Create your views here.
#编写装饰器
def wapper(f):
def inner(request,*args,**kwargs):
is_loin=request.COOKIES.get('is_login')
if is_loin=='True':
ret=f(request,*args,**kwargs)
return ret
else:
return redirect('login')
return inner
# 调用装饰器
@wapper
def index(request):
return render(request,'index.html')
# 登录函数设置COOKIE不变
def login(request):
if request.method=='GET':
return render(request,'login.html')
if request.method=='POST':
username=request.POST.get('username')
pwd=request.POST.get('pwd')
if username=='aaa' and pwd=='666':
ret=redirect('index')
ret.set_COOKIE('is_login',True)
# print('访问成功')
return ret
else:
return redirect('login')









前进,前进,不择手段的前进




{% csrf_token %}
用户名:

密码:











自然选择,前进四



2.3设置COOKIE的有效期

ret.set_COOKIE('name', 'AA',10)
ret.set_COOKIE('sex', 'male',10)

image-20210326221531916


2.5 COOKIE的其他设置

rep = HttpResponse(...) 或 rep = render(request, ...)

rep.set_COOKIE(key,value,...)
rep.set_signed_COOKIE(key,value,salt='加密盐',...)
参数:
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获取(不是绝对,底层抓包可以获取到也可以被覆盖)

2.6 COOKIE的缺点



  • COOKIE键值对存在与本地的浏览器文件安全性较低

例如

def login(request):
if request.method=='GET':
return render(request,'login.html')
if request.method=='POST':
username=request.POST.get('username')
pwd=request.POST.get('pwd')
if username=='aaa' and pwd=='666':
ret=redirect('index')
ret.set_COOKIE('is_login',True)
ret.set_COOKIE('name', 'AA')
ret.set_COOKIE('sex', 'male')
# print('访问成功')
return ret
else:
return redirect('login')

image-20210326215641189


3.seesion会话



  • session的相关数据(键值对)默认存储在服务端的数据库中django_session表中。



  • 一个用户,一个浏览器只保存一条记录



  • seesion的默认过期时间是两周,可以手动设置



  • 生成COOKIE为加密后的字符串,数据存储在django_session数据表之中



    • 可以在setting-global里面修改seesion_id的名称,与数据库表中的键相对应。

    • image-20210326215652168




3.1 一般使用

def login(request):
""" 用户名和密码登录 """
if request.method == 'GET':
form = LoginForm(request)
return render(request, 'login.html', {'form': form})
form = LoginForm(request,data=request.POST)
if form.is_valid():
# 用户输入正确,登陆成功
username = form.cleaned_data['username']
password = form.cleaned_data['password']
# 账号可能为邮箱或者是手机号
'''
查询逻辑:username=手机号或者是邮箱,但是验证码均等于验证码
(username=moblie_phone and password=password)or(username=email and password=password)
属于复杂查询条件,因此使用orm的Q查询
'''
user_obj = models.UserInfo.objects.filter(Q(email=username) | Q(moble_phOne=username)).filter(
password=password).first()
if user_obj:
'''登录成功为1'''
# session使用步骤
# 1.生成随机字符串
# 2.通过COOKIE发送到客户端
# 3.保存到服务端值
request.session['username'] = user_obj.username
# 上句代码可完成上述的所有操作。
request.session.set_expiry(60 * 60 * 24 * 14) # 设置session的时间为两周
return redirect('home')
# 登录失败
form.add_error('username', '用户名或密码错误')
return render(request, 'login.html', {'form': form})

3.2session和COOKIE的有效期



  • seesion的默认过期时间是两周,可以手动设置

request.session.set_expiry(60 * 60 * 24 * 14)


  • 逻辑可参考上述(一般使用)代码

image-20210326221800424

from django.shortcuts import render,redirect,HttpResponse
# Create your views here.
def index(request):
# is_login=request.session['is_login']
'''
1.从COOKIE里面拿出了session_id:xxx随机字符串拿出来
2、去django-session表里面查询到相对应的数据
3.反解密用户存储的数据,并获取用户的数据
'''
is_login = request.session.get('is_login')
if is_login==True:
return render(request,'index.html')
else:
return redirect('home')
def login(request):
if request.method=='GET':
return render(request,'login.html')
if request.method=='POST':
username=request.POST.get('username')
pwd=request.POST.get('password')
if username=='aa' and pwd=='300':
# 设置seession
request.session['is_login']=True
request.session['name']='AA'
'''
1、生成ssesion_id:随机字符串
2、在COOKIE里面加上了键值对:session_id:ZDsrf
3.将用户的数据进行加密并保存到DJANGO-SESSION表里面,形式为一条记录
# 数据库中session_key 随机字符串
# seesion_data:用户加密的数据

'''
return redirect('index')#redict里面的字符串为URL的别名,进行反向解析
else:
return HttpResponse('请正常登录')

3.3 seession的装饰器

装饰器函数一般要写在被装饰函数的上方,以免语法错误

def session_author(fn):
def inner(request,*args,**kwargs):
status=request.session.get('is_login')
if status:
ret=fn(request)
return ret
else:
# return redirect('login'),#使用reverse进行反向解析
return redirect(reverse('login'))
return inner

与COOKIE的装饰器相似。



  • 注:上述装饰器可用作判断用户是否登录,但是在django中使用较少。django中一般使用中间件判断用户是否登录。并设置对应的白名单。


3.4 Session操作。



  • 可以进行增删改查。



  • 增加就是登录时的写入,修改可以直接像字典一样进行修改。



  • 删除seesion

    def logout(request):
    # 清楚Session
    request.session.flush()
    return redirect('home')

    常用作用户注销登录的实现。



  • 获取seesion

    中间件中获取判断

    class AuthMiddleware(MiddlewareMixin):
    def proccess_request(self,request):中
    '''如果用户已登录,则request中赋值'''
    user_name=request.session.get('user_name',0)
    # 在中间件中获取值,不存在,则默认值是0,获取到用户的user_name
    userobj=models.UserInfo.objects.filter(user_name=user_name)
    # 根据用户的username去数据库中进行查询,查询到结果userobj赋值给request
    # 中,如果request中的tracer有值,则认定为已经登录,反之则认为没登录。
    request.tracer=userobj
    # 如果tracer的值比较多,则可以定义一个类,专门进行保存



  • 完整登录中间件模板

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import datetime
    from django.shortcuts import redirect
    from django.utils.deprecation import MiddlewareMixin
    from django.conf import settings
    from web import models
    class Tracer(object):
    def __init__(self):
    self.user = None
    self.price_policy = None
    self.project = None
    class AuthMiddleware(MiddlewareMixin):
    def process_request(self, request):
    """ 如果用户已登录,则request中赋值 """
    request.tracer = Tracer()
    user_id = request.session.get('user_id', 0)
    user_object = models.UserInfo.objects.filter(id=user_id).first()
    request.tracer.user = user_object
    # 白名单:没有登录都可以访问的URL
    """
    1. 获取当用户访问的URL
    2. 检查URL是否在白名单中,如果再则可以继续向后访问,如果不在则进行判断是否已登录
    """
    if request.path_info in settings.WHITE_REGEX_URL_LIST:
    return
    # 检查用户是否已登录,已登录继续往后走;未登录则返回登录页面。
    if not request.tracer.user:
    return redirect('login')
    # 登录成功之后,访问后台管理时:获取当前用户所拥有的额度
    # 方式一:免费额度在交易记录中存储
    # 获取当前用户ID值最大(最近交易记录)
    _object = models.Transaction.objects.filter(user=user_object, status=2).order_by('-id').first()
    # 判断是否已过期
    current_datetime = datetime.datetime.now()
    if _object.end_datetime and _object.end_datetime _object = models.Transaction.objects.filter(user=user_object, status=2, price_policy__category=1).first()
    request.tracer.price_policy = _object.price_policy
    # 方式二:免费的额度存储配置文件
    """
    # 获取当前用户ID值最大(最近交易记录)
    _object = models.Transaction.objects.filter(user=user_object, status=2).order_by('-id').first()
    if not _object:
    # 没有购买
    request.price_policy = models.PricePolicy.objects.filter(category=1, title="个人免费版").first()
    else:
    # 付费版
    current_datetime = datetime.datetime.now()
    if _object.end_datetime and _object.end_datetime request.price_policy = models.PricePolicy.objects.filter(category=1, title="个人免费版").first()
    else:
    request.price_policy = _object.price_policy
    """
    def process_view(self, request, view, args, kwargs):
    # 判断URL是否是以manage开头,如果是则判断项目ID是否是我创建 or 参与
    if not request.path_info.startswith('/manage/'):
    return
    project_id = kwargs.get('project_id')
    # 是否是我创建的
    project_object = models.Project.objects.filter(creator=request.tracer.user, id=project_id).first()
    if project_object:
    # 是我创建的项目的话,我就让他通过
    request.tracer.project = project_object
    return
    # 是否是我参与的项目
    project_user_object = models.ProjectUser.objects.filter(user=request.tracer.user, project_id=project_id).first()
    if project_user_object:
    # 是我参与的项目
    request.tracer.project = project_user_object.project
    return
    return redirect('project_list')



3.5 Session配置文件补充及存储


1.数据库存储

Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。

a. 配置 settings.py

SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)

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,默认修改之后才保存(默认)



b. 使用

def index(request):
# 获取、设置、删除Session中数据
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()


# 用户session的随机字符串
request.session.session_key

# 将所有Session失效日期小于当前日期的数据删除
request.session.clear_expired()

# 检查 用户session的随机字符串 在数据库中是否
request.session.exists("session_key")

# 删除当前用户的所有Session数据
request.session.delete("session_key")
# "session_key"指的是 request.session.session_key
request.session.set_expiry(value)
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。

2.缓存Session


  • 缓存,存储在另一台(缓存服务器)机器内存中的数据。一般结合redis使用

a. 配置 settings.py

SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置


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,默认修改之后才保存



b. 使用
同上

3.其他

文件Session

缓存+数据库Session

加密COOKIE Session

以上方式请点击参考文献进行观看。



4.装饰器的补充

def warper(f):
def inner(*args,**kwargs):
print('我是执行前的语句')
ret=f()
print('我是执行后的语句')
return ret# 返回原函数的返回结果
return inner
@warper#执行wapper函数把test1当做参数
def tes1():
print('***********')
return '我是原函数的返回结果'
print(tes1())

image-20210330185836720


5.知识梳理

image-20220105103839285


继续努力,终成大器!



推荐阅读
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 微信官方授权及获取OpenId的方法,服务器通过SpringBoot实现
    主要步骤:前端获取到code(wx.login),传入服务器服务器通过参数AppID和AppSecret访问官方接口,获取到OpenId ... [详细]
  • 我创建了一个新的AWSSSO(使用内部IDP作为身份源,因此不使用ActiveDirectory)。我能够登录AWSCLI、AWSGUI,但 ... [详细]
  • 有些网站设置了权限,只有在登录了之后才能爬取网站的内容,如何模拟登录,目前的方法主要是利用浏览器cookie模拟登录。浏览器访问服务器的过程在用户访问网页时,不论是通过URL输入域名或I ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • uniapp开发H5解决跨域问题的两种代理方法
    本文介绍了uniapp开发H5解决跨域问题的两种代理方法,分别是在manifest.json文件和vue.config.js文件中设置代理。通过设置代理根域名和配置路径别名,可以实现H5页面的跨域访问。同时还介绍了如何开启内网穿透,让外网的人可以访问到本地调试的H5页面。 ... [详细]
  • struts2重点——ValueStack和OGNL
    一、值栈(ValueStack)1.实现类:OGNLValueStack2.对象栈:CompoundRoot( ... [详细]
  • 渗透测试基础bypass绕过阻挡我们的WAF(下)
    渗透测试基础-bypass ... [详细]
  • 【Python 爬虫】破解按照顺序点击验证码(非自动化浏览器)
    #请求到验证码base64编码json_img_datajson_raw.get(Vimage)#获取到验证码编码 #保存验证码图片到本地defbase64_to_img(bstr ... [详细]
  • Request对象和Response对象request:(请求)当一个页面被请求时,Django就会创建一个包含本次请求原信息的HttpRequest对象。Djang ... [详细]
  • 跨站的艺术XSS Fuzzing 的技巧
    作者|张祖优(Fooying)腾讯云云鼎实验室对于XSS的漏洞挖掘过程,其实就是一个使用Payload不断测试和调整再测试的过程,这个过程我们把它叫做F ... [详细]
  • 这篇文章主要介绍PHP如何使用在全部作用域中始终可用的内置变量,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要 ... [详细]
  • 最近在做一个项目,但是由于之前一个项目也同时部署在同一台tomcat下,所以出现了sessionId的冲突,描述一下冲突过程:1.打开浏览器访问第一个项目(配置在根目录)2.打开另一标签 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
author-avatar
手浪用户2502941303
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有