会话技术(Cookie / Session / Token)

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

假如有一个恶意的网站链接指向我的网站链接,如果当前某个用户已经登录到我的网站上,那么当用户点击了恶意网站这个链接时,我的网站以为是当前用户发生的请求,但其实是恶意网站伪造的请求

Django 里如何使用 CSRF 防护

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

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

  3. 其次,在所有的 POST 表单元素时,需要加上一个 {% csrf_token %} 标签,django 第一次响应来自某个客户端的请求时,会在服务器随机生成一个token值,把该token值放在cookie中,然后每次POST请求都会带上这个token值,防止恶意网站请求伪造,避免发生CSRF攻击。

  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信息: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)
    

    示例:

    # 设置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’)

#### 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]:                                               
    > ```
  - 在前部添加了混淆串

  #### 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() 
  ```



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

#### Cookie和Session的关系

Cookie是一个事件存储在客户端(浏览器),Session是一个对象存储在服务端;Session依赖于Cookie,用户每次请求服务器请求头都会携带Cookie,Cookie中保存了session标识符,服务器通过该标识符获取到跟请求对应的session对象。

  • Cookie和Session的关系:

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

3. Token

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

  1. uuid1():这个是根据当前的时间戳和MAC地址生成的,最后的12个字符例如408d5c985711对应的就是MAC地址,因为是MAC地址,那么唯一性应该不用说了。但是生成后暴露了MAC地址这就很不好了。
  2. uuid3(namespace,str):里面的namespace是计算机的名字,str是需要加密的具体字符串通过MD5生成的
    In [14]: uuid.uuid3(uuid.NAMESPACE_DNS,‘python1’).hex
    Out[14]: ‘419dde702d66309793ead236e60296e9’
  3. uuid4():这是基于随机数的uuid,既然是随机就有可能真的遇到相同的,但这就像中奖似的,几率超小,因为是随机而且使用还方便,所以使用这个的还是比较多的。
  4. uuid5():这个看起来和uuid3()并没有什么不同,写法一样,也是由用户来指定namespace和字符串,不过这里用的散列并不是MD5,而是SHA1.
    In [15]: uuid.uuid5(uuid.NAMESPACE_DNS,‘python1’).hex
    Out[15]: ‘e3392af90f48578bb4d9f595c3cbeb4d’
    如果需要真的唯一的标识符,推荐使用uuid3 / uuid5
#### 如果在MySQL中存储token需要建立有关token字段的表格,还可以使用 redis / mongodb

import uuid

token = uuid.uuid4().hex # 使用uuid创建token,hex代表16进制
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)**

你可能感兴趣的:(Django文档)