Django回顾【六 】

目录

一、Cookie和Session

【1】Cookie

【2】Session

二、中间件

【1】 什么是中间件

【2】作用

【3】自定义中间件

三、CSRF认证相关

【1】CSRF是什么

【2】CSRF攻击原理

【3】CSRF攻击防范

四、auth的使用

【1】author是什么

【2】auth模块常用方法

authenticate()

login(HttpRequest, user)

logout(request)

is_authenticated()


一、Cookie和Session

【1】Cookie

Cookie是客户端浏览器上的键值对 ----> 为了做会话保持

怎么来的?

  • 服务端写入的
    • 服务端在返回的响应头中写入
    • 浏览器会自动取出来
    • 存起来

key value 形式

  • 过期时间
    • path
    • http only
    • 。。。

只要浏览器中有cookie,再次向当前域发送请求,都会自动携带

  • 携带在请求头中的cookie字段中
  • cookie:"name=lqz;age=19"

不安全问题:cookie中发了敏感数据 ---> 客户能看到

cookie设置:obj.set_cookie()
cookie取值:request.COOKIES.get()
清空:      request.COOKIES.clear()

【2】Session

我们需要让cookie变的安全 ---> 敏感数据不在cookie中方法,而放在session中

  • session是服务端的键值对
  • session跟cookie有什么关系呢?
    • {111:{name:lqz,age:19,password:123},222:{name:zs,age:19,password:666}}
      • 把key,以cookie的形式,存到浏览器中
        • sessionid:111
      • 当前浏览器以后再发请。就会携带 过来
      • 我们根据带过来的cookie:111 ----> 从 session中取出对应的数据

session的使用 ---> 必须要先迁移表 ---> django-session表不存在

  • session存在服务端的 ---> 默认情况下存在 ---> django-session表中
    • 配置文件
    • django项目有两套配置文件:内置一套,项目自己一套
    • SESSION_ENGINE = 'django.contrib.sessions.backends.db'
# django-session表的字段
session_key:     sessionid:随机字符串
session_data:    真正的数据--->加密了
expire_date:     过期时间

session的使用 

取值:request.session.get()
赋值:request.session['name']='l

session的本质执行原理

'''
1 咱么写了request.session['name']='lqz',本质就是向session 对象中放入了name=lqz

2 当前视图函数结束----> 经过 【中间件】 ---> 返回给了前端
    - django内置了一个session中间件
    - 判断:request.session有没有变化,如果有变化
        - 情况一:django-session表中没有数据
        在表中创建出一条数据,随机生成一个字符串[随机字符串session_key],
        把数据存入django-session表
            session_key: adsfasd
            session_data: name=lqz  加密后存到里面
            把随机字符串写入到cookie中: sessionid:adsfasd
        - 情况二:django-session表中有数据
            把session中所有的值--》加密后--》更新到django-session表的session_data中,其他不变

3 下次再发请求进入任意视图函数---> 又会经过  【中间件】---> 视图函数
    - 视图函数中取session:request.session.get('age')
    - 浏览器发请求---> 携带cookie过来---> 到了中间件---> 根据sessionid取出随机字符串
    - 拿着随机字符串去django-session中查【session_key】---> 能查到就把 session_data的数据解密
    ---> 放到request.session中
    - 后续视图函数中,才能取出值

'''

session的中间件把上述内容完成了:procee_request      process_response

django.contrib.sessions.middleware.SessionMiddleware 

二、中间件

【1】 什么是中间件

中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。

【2】作用

  1. 全局的请求拦截 ---> 如果它没有登录 ---> 就不允许访问
  2. 拦截所有请求,获取请求的ip地址
  3. 记录所有用户的访问日志
  4. 统一在响应头中加数据

【3】自定义中间件

中间件中主要有几个方法:就是一个类,类中有几个方法

process_request(self,request) 
# 请求来了就会走
process_response(self, request, response) 
# 请求走了就会走
process_view(self, request, callback, callback_args, callback_kwargs) 
# 视图函数执行之前调用
process_template_response(self,request,response) 
# 渲染模板之前会走
process_exception(self, request, exception) 
# 视图函数中出现异常了才执行

django内置一些中间件 ---> 增强了djagno的功能

  • request.session
  • request.user

post请求提交数据,拦截了---> csrf认证

process_request和process_response

当用户发起请求的时候会依次经过所有的的中间件,这个时候的请求时process_request,最后到达views的函数中,views函数处理后,在依次穿过中间件,这个时候是process_response,最后返回给请求者。

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    # session相关的中间件
    'django.contrib.sessions.middleware.SessionMiddleware',
    # 公共中间件---> 访问不带 / 路径,如果有带 / 的路径,他会让你重定向到这个地址
    'django.middleware.common.CommonMiddleware',
    # csrf认证    xss  cors
    'django.middleware.csrf.CsrfViewMiddleware',
    # 认证:request.user---> 这个中间件做的
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # django的消息框架---> flask--> 闪现
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

自定义中间件来使用,记录用户的请求地址和user-agent

class SaveRemoteAddr(MiddlewareMixin):
    def process_request(self, request):
        # request是WSGIRequest 的对象
        # print(request.session) # 一定要保证,session的中间件要在上面
        # 这个request就是当次请求的request
        # 取出ip
        ip = request.META.get('REMOTE_ADDR')
        user_agent = request.META.get('HTTP_USER_AGENT')
        print(ip)
        print(user_agent)
        # return HttpResponse('不让你看了') # 不会再走视图函数了
'''
能返回的情况:
1 None,表示执行完这个代码,继续往后执行---> 还有中间件,继续执行--> 最后进视图函数
2 四件套,后续不走了,中间件的process_response---> 直接返回给浏览器了
'''

中间件,在响应头加入访问时间

import datetime
class AddHeaderMiddleWare(MiddlewareMixin):
    def process_response(self, request, response):
        # request中有没有session? 有
        # request 如果在视图函数中,往request中放了值,在这里,就可以取出来request.xxx
        # print(request.xxx)
        # 所有cookie中都带
        # response.set_cookie('xxxxx', 'asdfds')
        # 写入到响应头,访问服务端的时间
        response['ttt'] = datetime.datetime.now()
        return response  # 一定要返回response对象

三、CSRF认证相关

【1】CSRF是什么

CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

【2】CSRF攻击原理

在同一个浏览器中,如果登录了A网站,没有退出,在B网站中,向A网站发送请求,浏览器会自动携带A网站的cookie,对于A网站后端来讲, 它就分辨不清到底是用户真实发的请求,还是黑客网站发的请求【都会携带用户真实的cookie】。

【3】CSRF攻击防范

Django解决了这个问题 ---> 只要发送post请求,必须携带一个csrf_token 随机字符串(后端给的)。

这个随机字符串可以带的位置

1 请求体中(urlencoded,form-data):{csrfmiddlewaretoken:asdfasdf}
2 放在请求头中:'X-CSRFToken':asdfasdfasd
3 ajax提交数据:默认是urlencoded,放在请求体中没有任何问题

$.ajax({
    method: 'post',
    data: {username, password, csrfmiddlewaretoken},
    success: function (res) {
    console.log(res)
    }
})

4 ajax提交,使用json格式 ---> 就不能放在请求体中,只能放在请求头中:

$.ajax({
    method: 'post',
    headers:{'X-CSRFToken':csrfmiddlewaretoken},
    contentType: 'application/json',
    data: JSON.stringify({username, password}),
    success: function (res) {
    console.log(res)
    }
})

注:

  • post 提交的数据,都是从request.POST中取,前提是:必须是urlencoded和form-data格式
    • 如果是json是取不到的
  • 如果使用ajax发送请求
    • redirect  render就用不了了
    • 尽量使用JsonResponse

四、auth的使用

【1】author是什么

Auth模块是Django自带的用户认证模块:

我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,这还真是个麻烦的事情呢。

Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点。它内置了强大的用户认证系统–auth,它默认使用 auth_user 表来存储用户数据。

默认的用户表示auth_user

创建一个用户:可以用代码,可以用命令

【2】auth模块常用方法

from django.contrib import auth

authenticate()

提供了用户认证功能,即验证用户名以及密码是否正确,一般需要username 、password两个关键字参数。

如果认证成功(用户名和密码正确有效),便会返回一个 User 对象。

authenticate()会在该 User 对象上设置一个属性来标识后端已经认证了该用户,且该信息在后续的登录过程中是需要的。

用法:

user = authenticate(username='usernamer',password='password')

login(HttpRequest, user)

登录认证通过,调用一下这个方法,以后从request.user中才能取出当前登录用户。

用法:

from django.contrib.auth import authenticate, login
   
def my_view(request):
  username = request.POST['username']
  password = request.POST['password']
  user = authenticate(username=username, password=password)
  if user is not None:
    login(request, user)
    # Redirect to a success page.
    ...
  else:
    # Return an 'invalid login' error message.
    ...

logout(request)

该函数接受一个HttpRequest对象,无返回值。

当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。

用法:

from django.contrib.auth import logout
   
def logout_view(request):
  logout(request)
  # Redirect to a success page.

is_authenticated()

判断当前用户是否登录

  • 不能使用request.user 是否有值来判断,因为他一直有值
  • request.user.is_authenticated()

用法:

def my_view(request):
  if not request.user.is_authenticated():
    return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))

你可能感兴趣的:(django,python,后端)