会话技术

CSRF ( cross site request forgery ) 跨站点请求伪造

假如有一个恶意的网站链接指向我的网站链接,如果当前某个用户已经登录到我的网站上,那么当恶意网站的用户点击这个链接时,我的网站以为是当前用户发生的请求,但其实是恶意网站伪造的请求。django 第一次响应来自某个客户端的请求时,会在服务器随机生成一个token值,把该token值放在cookie中,然后每次POST请求都会带上这个token值,防止恶意网站请求伪造,避免发生CSRF攻击。

Django 里如何使用 CSRF 防护
  1. 首先,最基本的原则是:GET 请求不要存在副作用。也就是说任何处理 GET 请求的代码对资源的访问都一定要是“只读“的。

  2. 启用 django.middleware.csrf.CsrfViewMiddleware 这个中间件

  3. 其次,在所有的 POST 表单元素时,需要加上一个{% csrf_token %} 标签

  4. 在渲染模块时,使用 RequestContext。RequestContext 会处理 csrf_token 这个标签, 从而自动为表单添加一个csrfmiddlewaretoken 的 input标签

会话技术

HTTP被设计为”无状态”,每次请求都处于相同的空间中。在一次请求和下一次请求之间没有任何状态保持,我们无法根据请求的任何方面(IP地址,用户代理等)来识别来自同一人的连续请求。上图很明显的展示了Django的session与cookie的实现原理。服务器会生成两份相同的cookie字符串,一份保存在本地,一份发向请求的浏览器。浏览器将收到的cookie字符串保存下来,当下次再发请求时,会将信息与这段cookie一同发送到服务器,服务器得到这段cookie会与本地保存的那份判断是否相同,如果相同就表示用户已经登录成功,保存用户登录成功的状态。Django的session保存在数据库中的数据相当于一个大字典,key为cookie的字符串,value仍是一个字典,字典的key和value为用户设置的相关信息。这样就可以方便的存取session里面的信息。

  • 验证用户身份信息
  • 服务器如何识别客户端
  • Http在Web开发中基本都是短连接
  • 请求生命周期
    • 从Request开始
    • 到Response结束

种类

1. Cookie
  • 客户端会话技术,数据存储在客户端

  • 存储形式:键值对存储

  • 特性:

    • 支持过期时间
    • 默认Cookie会自动携带本网站所有的Cookie
    • Cookie不能跨域名,不能跨网站
    • 通过HttpResponse操作客户端
  • Django中使用Cookie

    # 设置cookie,从服务器返回的response中设置
    response  = redirect(path)   # 重定向到某个指定的路径下
    response.set_cookie(key,value,max_age=0)    # 直接设置cookie的值和value,max_age是过期时间,0是默认,None是永久,接上数字是具体时间,用s做单位。
    如:response.set_cookie('name',person.name,max_age=3600)
    
    # 获取cookie,从客户端请求中获得
    name = request.COOKIES.get('name')
    response = render(request,'home.index',contex=({'name':name})  
    return response
    
    # 清除cookie,从response清除
    response = redirect('namespace:name')
    response.delete_cookie('name')
    
    ~ 读取请求头中的cookie信息:request.COOKIES - [key] -> value
    ~ 通过响应将cookie写入浏览器:response.set_cookie(key, value, 时间)
    ~ 删除cookie:自动过期 / response.delete_cookie(key)
    ~ 如果要防范恶意的伪造或篡改cookie,可以使用带签名的cookie
    
    - response.set_signed_cookie(key, value, salt, 时间)
    - request.get_signed_cookie(key, salt)
    
2. Session
  • 服务端会话技术,数据存储在服务器中

  • 默认Session存储在内存中

  • Django默认把Session持久化到数据库中

  • Django中Session的默认过期时间是14天

  • Primary key 是字符串

  • 数据存储使用了数据安全

    • 使用了Base64编码:将任意的二进制数据处理成64个文字符号(0-9a-zA-Z+/)的编码方法

      Python:b64encode() 编码 / b64decode()解码

      JavaScript:btoa()编码 / atob() 解码 – 较新版本的浏览器

      百分号编码 - URL中不能出现非ASCII码字符,有些字符还有特殊含义,
      如果URL中出现了非ASCII码字符和特殊符号必须处理成百分号编码
      ~ Python - quote() 编码 / unquote() 解码
      ~ JavaScript - encodeURIComponent() / decodeURIComponent()

      In [1]: from urllib.parse import quote, unquote
      
      In [2]: quote('苹果')
      Out[2]: '%E8%8B%B9%E6%9E%9C'
      
      In [3]: a = 'https://www.baidu.com'
      
      In [4]: a + quote('苹果')
      Out[4]: 'https://www.baidu.com%E8%8B%B9%E6%9E%9C'
      
      In [5]: a = 'https://www.baidu.com/?'
      
      In [6]: a + quote('苹果')
      Out[6]: 'https://www.baidu.com/?%E8%8B%B9%E6%9E%9C'
      
      In [7]: unquote('https://www.baidu.com/?%E8%8B%B9%E6%9E%9C')
      Out[7]: 'https://www.baidu.com/?苹果'
      
      In [8]:                                               
      
    • 在前部添加了混淆串

  • Cookie和Session的关系:session依赖于cookie,cookie中保存了session的标识符,每次请求服务器,请求头都会携带cookie,这样就可以将session表示符发送给服务器,服务器通过该标识符获取到跟请求对应的session对象

  • Django中是使用session

    # 设置session,一开始需要在project中setting里的middleware中添加上'django.contrib.sessions.middleware.SessionMiddleware',
    #默认是加上的,在request中设置session
    request.session['name'] = person.name
    request.session.set_expiry(60)   # 设置过期时间,单位是s
    
    
    # 获取session,也是从request中获取
    name = request.session.get('name')
    
    
    # 删除session,在response中删除
    response.delete_cookie('sessionid')  # 在客户端删除session
    del request.session['name']       #  在服务器端删除session
    request.session.flush() 
    
  • 过期时间

    settins.py 文件中添加:

    # 配置将会话放入缓存中
    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
    # 配置缓存的过期时间为1天
    SESSION_COOKIE_AGE = 86400
    
3. Token

使用Python中uuid函数来生成用户的令牌

  1. uuid1():这个是根据当前的时间戳和MAC地址生成的,最后的12个字符408d5c985711对应的就是MAC地址,因为是MAC地址,那么唯一性应该不用说了。但是生成后暴露了MAC地址这就很不好了。
  2. uuid3():里面的namespace和具体的字符串都是我们指定的,然后呢···应该是通过MD5生成的,这个我们也很少用到,莫名其妙的感觉。
  3. uuid4():这是基于随机数的uuid,既然是随机就有可能真的遇到相同的,但这就像中奖似的,几率超小,因为是随机而且使用还方便,所以使用这个的还是比较多的。
  4. uuid5():这个看起来和uuid3()貌似并没有什么不同,写法一样,也是由用户来指定namespace和字符串,不过这里用的散列并不是MD5,而是SHA1.
# 如果需要在MySQL中存储token需要建立有关token字段的表格 / redis / mongodb
import uuid

token = uuid.uuid4().hex  # 使用uuid创建token
response.set_cookie('token', token)  # 将token传给浏览器


# 获取token,在request中获取token
person.token = request.COOKIES.get('token')

# 清除token,在response中清除
response.delete_cookie('token')

在存储session,cookie,token的时候还应该对用户的信息进行加密(MD5 / SHA1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值