Django(第三周)

一、状态码

当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在  的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。

HTTP状态码的英文为HTTP Status Code。下面是常见的HTTP状态码:

200 - 请求成功

301 - 资源(网页等)被永久转移到其它URL

404 - 请求的资源(网页等)不存在

500 - 内部服务器错误

状态码的分类:

HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:

1** - 信息,服务器收到请求,需要请求者继续执行操作

2** - 成功,操作被成功接收并处理

3** - 重定向,需要进一步的操作以完成请求

4** - 客户端错误,请求包含语法错误或无法完成请求

5** - 服务器错误,服务器在处理请求的过程中发生了错误

二、Cookie 

Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。实际上cookie是一个很小的文本文件,是浏览器储存在用户的机器上的。Cookie是纯文本,没有可执行代码。储存一些服务器需要的信息,每次请求站点,会发送相应的cookie,这些cookie可以用来辨别用户身份信息等作用。

特点:

Cookie以键值对的格式进行信息的存储

Cookie基于域名安全,不同域名的Cookie是不能互相访问的,如访问jd.com时向浏览器中写了Cookie信息,使用同一浏览器访问baidu.com时,无法访问到jd.com写的Cookie信息。

当浏览器请求某网站时,会将浏览器存储的跟网站相关的所有Cookie信息提交给网站服务器

类型: 

可以按照过期时间分为两类:会话cookie和持久cookie。会话cookie是一种临时cookie,用户退出浏览器,会话Cookie就会被删除了,持久cookie则会储存在硬盘里,保留时间更长,关闭浏览器,重启电脑,它依然存在,通常是持久性的cookie会维护某一个用户周期性访问服务器的配置文件或者登录信息。

Cookie的产生流程:

未携带cookie

服务器返回cookie到客户端

再次访问时,客户端会携带着服务器返回的cookie进行访问。 

Cookie的所在域: 

 

服务器1,服务器2,服务器3都与同一个第三方广告服务器签订了合作协议,当我们点击了服务器1里面的广告,进入到广告页面去看了商品a,cookie就会把这一举动记录下来,放在这个广告域的cookie中;当我们点击了服务器2里面的广告,进入到广告页面买了商品b,cookie也会把这一举动记录下来,放在这个广告域的cookie中;当我们访问服务器3里面的广告,广告端服务器检查你的cookie时就会发现你浏览过a,买过b,然后针对这些行为做一些什么举动大家懂得都懂 

Cookie的配置:

views.py:

def cookie_(request):
    response = HttpResponse()
    response.set_cookie('user', 'admin')
    response.set_cookie('area', 'China')
    response.set_cookie('city', 'Beijing')
    return response

urls.py:

path('cookie/', views.cookie_)

效果:

当我们没有访问 http://127.0.0.1:8000/cookie/ 时

 当我们访问 http://127.0.0.1:8000/cookie/ 后

可以看见通过set_cookie方法我们成功设置了cookie,但是如果没有设置cookie的有效期,那么在浏览器关闭之后,cookie会自动删除,cookie的有效期可以通过max_age参数(单位为秒)进行设置

修改views.py中的cookie_视图

def cookie_(request):
    response = HttpResponse()
    response.set_cookie('user', 'admin', max_age=10)
    response.set_cookie('area', 'China')
    response.set_cookie('city', 'Beijing')
    return response

重启django服务

 user的有效期被成功设置为10秒,10秒钟后我们在访问主页,发现有效期为十秒的cookie就已经没了

 当然,expires参数也可以设置cookie的有效时常,但当他俩同时存在且都以秒为单位时,系统使用的max_age参数的值;当expires参数不是以秒为单位时,系统使用的是expires参数的值

expires参数值的三种形式:

1. 以秒为单位,传入一个整数

2. 格林尼治时间,格式如:Thu, 20-May-2021, 21:12:12, GMT

3. datetime.datetime对象,格式如:datetime.datetime(2021,5,20,21,12,12)

secure参数:值为True时,只允许Https请求方式访问cookie;值为False时,没有限制

httponly参数:值为True时,会组织客户端的JavaScript访问cookie

domain参数:表示可允许访问cookie的域名

删除cookie(delete_cookie方法):

def cookie_(request):
    response = HttpResponse()
    response.set_cookie('user', 'admin', max_age=10, expires=20)
    response.set_cookie('area', 'China')
    response.set_cookie('city', 'Beijing')
    response.delete_cookie('city')
    return response

后台获取cookie:

views.py:

def get_cookie(request):
    cookies_ = request.COOKIES
    return HttpResponse(cookies_)

urls.py:

path('get_cookie/', views.get_cookie)

三、Session

又称会话控制Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在Session对象中。

Session和Cookie的区别:Session存放于服务器中,Cookie存放于本地

因为session存放于服务器中,所以我们会用到数据库,具体操作在此处不用理解,后面会着重介绍

配置settings文件:

SESSION_ENGINE = 'django.contrib.sessions.backends.db'

db:配置的是关系型数据库(例如:Mysql)

SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' 

cached_db:配置的是混合型的数据库(关系型数据库和非关系型数据库都行)

SESSION_ENGINE = 'django.contrib.sessions.backends.cache'    

cache:配置的是非关系型数据库(例如:Redis)

        SESSION_CACHE_ALIAS = "default"     如果是非关系型数据库,需要指定缓存的默认库

配置mysql数据库:

mysql的安装和配置:

参考连接:https://www.cnblogs.com/sui776265233/p/10673003.htmlhttps://www.cnblogs.com/sui776265233/p/10673003.html

推荐个软件:Navicat for MySQL 

Navicat for MySQL 是管理和开发 MySQL 或 MariaDB 的理想解决方案。它是一套单一的应用程序,能同时连接 MySQL 和 MariaDB 数据库,并与 Amazon RDS、Amazon Aurora、Oracle Cloud、Microsoft Azure、阿里云、腾讯云和华为云等云数据库兼容。这套全面的前端工具为数据库管理、开发和维护提供了一款直观而强大的图形界面。

收费软件,有钱的请支持正版软件,没钱的可以参考链接https://www.cnblogs.com/yinfei/p/11427259.html进行安装

因为一个项目只用到一次数据库的配置,代码不用记,现查就好

Navicat for MySQL配置:

左上角文件 -> 新建连接 -> mysql -> 输入连接名(此处以django为例),和自己mysql数据库的密码 ->

右键点击连接 -> 新建数据库 -> 输入数据库名(此处以dj_test为例),选择字符集utf-8

settings.py:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'dj_test',    # 数据库名称
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'USER': '用户名',
        'PASSWORD': '用户密码'
    }
}

SESSION_ENGINE = 'django.contrib.sessions.backends.db'


首先,我们需要下载一个第三方库:pymysql

然后在__init__.py文件中添加以下代码

from pymysql import install_as_MySQLdb

install_as_MySQLdb()

然后在项目文件夹的terminal终端中执行:python manage.py migrate

执行完在Navicat for MySQL相应的数据库中生成了很多张数据表

 

我们的session一般就是保存在生成的django_session表中

我们尝试添加一个session

view.py:

def set_session(request):
    request.session['time'] = '2021-5-20'
    request.session['country'] = 'Chine'
    # 设置session的有效期,此处设置成10秒
    request.session.set_expiry(10)
    return HttpResponse('Session添加成功!')

urls.py:

path('session/', views.set_session)

我们重启django服务,访问 http://127.0.0.1:8000/session/ ,刷新Navicat for MySQL中的界面,就可以看到session被保存到了django_session表中,只不过是加了密的形式

可以看见我们的session成功保存在了mysql数据库中

配置Redis数据库:

首先需要安装一个第三方库:django_redis

在redis desktop manager中创建一个连接:点击最下面中间的connect to redis server -> 输入相关信息(django,120.0.0.1,6379)

然后在settings.py文件中添加以下代码

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/0",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}


SESSION_ENGINE = 'django.contrib.sessions.backends.cache'    
SESSION_CACHE_ALIAS = "default"

我们重启django服务,访问 http://127.0.0.1:8000/session/

可以看见我们成功把session信息保存到了redis数据库中,因为我们设置的有效期是10s,所以在10s后鼠标右键django,选择reload,发现session信息被删除了

 session的删除:

request.session.flush()
request.session.clear()

clear:删除存储中的值,但是session还是存在的

flush:删除存储中的session,把整个session完全删除

四、类视图

类视图的定义:

使用类来定义的视图,称为类视图

与函数视图的区分:

以函数的方式定义的视图称为函数视图,函数视图便于理解。

函数视图的缺点:遇到一个视图对应的路径提供了多种HTTP请求方式的支持时,便需要在一个函数中编写不同的业务逻辑,代码可读性与复用性都不佳。

使用类视图的好处:

1.代码可读性好。

2.类视图相对于函数视图有更高的复用性,如果其他地方需要用到某个类视图的特定逻辑,直接copy该类视图即可。

比如,当我们要处理不同的请求方式:

函数视图:

def deal(request):
    if request.method == 'GET':
        return HttpResponse('GET请求!')
    elif request.method == 'POST':
        return HttpResponse('POST请求!')
    elif request.method == 'PUT':
        return HttpResponse('PUT请求!')
    elif request.method == 'CONNECT':
        return HttpResponse('CONNECT请求!')
    else:
        return HttpResponse('其他请求!')

类视图:

class Deal(View):
    def get(self, request):
        return HttpResponse('GET请求!')

    def post(self, request):
        return HttpResponse('POST请求!')

    def put(self, request):
        return HttpResponse('PUT请求!')

    def connect(self, request):
        return HttpResponse('CONNECT请求!')

类视图的定义和使用:

首先需要在 views.py 文件中进行导包:

from django.views import View

定义的类视图必须继承于导入的 View 类

注意事项:

定义类视图中的方法时,get方法就是用来处理get请求的,post方法就是处理post请求的...每个方法用来处理对应的请求方式(方法名不能修改,必须是是请求方法)

类视图分发路由:path('路径/',  views.类名.as_view())

views.py

class Deal(View):
    def get(self, request):
        response = HttpResponse()
        response.write('<title>类视图</title>')
        response.write('<b>类视图下处理get请求</b>')
        return response

urls.py

path('class/', views.Deal.as_view())

效果:

类视图装饰器: 

装饰器的作用:装饰器实质上就是一个函数,其可以让其他函数在不去改变任何代码的前提下增加额外的功能,装饰器的返回值是一个函数对象

我们首先在 views.py 中定义一个装饰器,再定义一个类视图

def decorator(function, *args, **kwargs):
    def wrapper(request, *args, **kwargs):
        print('装饰器成功被使用!')
        return function(request, *args, **kwargs)

    return wrapper


class Deal(View):
    def get(self, request):
        response = HttpResponse()
        response.write('<title>类视图</title>')
        response.write('<b>类视图下处理get请求</b>')
        return response
    
    def post(self, request):
        response = HttpResponse()
        response.write('<title>类视图</title>')
        response.write('<b>类视图下处理post请求</b>')
        return response

那么如何使用装饰器呢?有两种方法:①. 装饰器(被装饰函数).(传入参数)

                                                             ②. 语法糖:在要被装饰的函数上方加 @装饰器名

第①种方法在urls中分配路由:

path('class/', views.decorator(views.Deal.as_view()))

相当于先给 views.py 中的 decorator 函数分配路由,再把 views.py 中的 Deal 类视图作为参数传递

结果:无论发送get请求还是post请求,都会被装饰

注意:方法①添加装饰器会为类视图中所有的方法添加装饰器

第②种方法:

使用语法糖进行装饰首先需要导包

from django.utils.decorators import method_decorator

第一种语法糖格式:在类视图上方进行装饰

views.py

@method_decorator(decorator, name='dispatch')
class Deal(View):
    def get(self, request):
        response = HttpResponse()
        response.write('<title>类视图</title>')
        response.write('<b>类视图下处理get请求</b>')
        return response

    def post(self, request):
        response = HttpResponse()
        response.write('<title>类视图</title>')
        response.write('<b>类视图下处理post请求</b>')
        return response

使用我们前面导入的method_decorator,第一个参数传入我们自己写的装饰器,name参数值必须是请求方式,当它为dispatch时,会为类视图中所有的方法添加装饰器;当他为get时,会为类视图中的get方法添加装饰器;当他为post时,会为类视图中的post方法添加装饰器

第二种语法糖格式:在类视图的方法上进行装饰

class Deal(View):
    @method_decorator(decorator)
    def get(self, request):
        response = HttpResponse()
        response.write('<title>类视图</title>')
        response.write('<b>类视图下处理get请求</b>')
        return response

    def post(self, request):
        response = HttpResponse()
        response.write('<title>类视图</title>')
        response.write('<b>类视图下处理post请求</b>')
        return response

在这种方法下就不用设置 name 参数的值,且只有添加了语法糖的方法在执行时会被装饰

五、中间件 

Django中的中间件:django中的中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出。中间件的设计为开发者提供了一种无侵入式的开发方式,增强了Django框架的健壮性。我们可以使用中间件,在Django处理视图的不同阶段对输入或输出进行干预

内置中间件介绍

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

1. django.middleware.security.SecurityMiddleware:做了一些安全处理的中间件。比如设置XSS防御的请求头,比如做了http协议转为https协议的工作等。

2. django.contrib.sessions.middleware.SessionMiddleware:session中间件。会给request添加一个处理好的session对象。

3. django.middleware.common.CommonMiddleware:通用中间件,会处理一些URL,比如baidu.com会自动的处理成www.baidu.com。比如/blog/111会处理成/blog/111/自动加上反斜杠。

4. django.middleware.csrf.CsrfViewMiddleware:保护中间件,在提交表单的时候会必须加入csrf_token,cookie中也会生成一个名叫csrftoken的值,也会在header中加入一个HTTP_X_CSRFTOKEN的值来放置CSRF攻击。SessionMiddleware必须出现在CsrfMiddleware之前。

5. django.contrib.auth.middleware.AuthenticationMiddleware:用户授权中间件。会给request添加一个user对象的中间件。该中间件必须在sessionmiddleware后面。

6. django.contrib.messages.middleware.MessageMiddleware:消息处理中间件。为了在多个模板中可以使用我们返回给模板的变量,并且简化操作。

7. django.middleware.clickjacking.XFrameOptionsMiddleware:防止通过浏览器页面跨Frame出现clickjacking(欺骗点击)攻击出现。

拓展:

一、 跨站点请求伪造攻击(Cross Site Request Forgery,简称CSRF):

利用浏览器cookie自动发送的特点。如果浏览器中的cookie保存了用户信息,该攻击利用了cookie共享机制获取了用户信息,因此可以正常通过系统的鉴权认证,实现非法操作。

下面以网上银行转账的例子来说明该攻击的流程。

1. 小明在网上银行(bank.com)转账,浏览器cookie记录了小明的用户信息。

2. 小明在未关闭浏览器的情况下,又新建了页面开始浏览帖子(sns.com)。

3. 小黑是个黑客,已经将伪造的请求链接包含在sns.com的页面中。

4. 小明点中了小黑提供的伪造链接,那么该请求将会使用cookie中的合法信息,通过了银行的认证系统,实现小黑的非法操作。

这样就实现了跨站点请求伪造攻击。

防御措施:

解决跨站点请求伪造攻击,一般有以下两种方法:Referer校验,Token校验

referer校验

在 HTTP 协议的请求头部含有一个字段叫 Referer,它记录了本次请求的来源地址。例如从A网站跳到B网站,那么在B网站的看到的referer值就是A网站的域名。

在上面的银行转账例子的攻击中,银行系统接收到的攻击请求的referer是sns.com。如果该系统增加了referer校逻辑,就可以判断本次请求是否来自本系统bank.com,如果不是则拒绝。因此如果银行系统看到请求的referer是sns.com,则可以拒绝访问。注意,第一次访问时,referer值会为空。所以referer校验的策略是,允许referer值是本服务域名和空值的请求通过。

Token校验

token校验的原理是用户第一次登陆成功之后,系统给用户颁发随机且唯一的token,用户下次请求的时候,将该token作为参数传到后台,后台通过过滤器或者拦截器校验该token是否合法。若合法,则放行,不合法则拒绝访问。前端可以把token值存在请求头或者请求参数中,都可以。

二、Clickjacking攻击

clickjacking保护是攻击者在自己的病毒网站上,写一个诱惑用户点击的按钮,然后使用iframe的方式将受攻击的网站(比如银行的网站)加载到自己的网站上去,并将其设置为透明的,用户就看不到了,然后再把受攻击的网站(比如银行网站)的转账按钮定位到病毒网站的按钮上,这样用户在点击病毒网站上的按钮的时候,实际上点击的是受攻击的网站(比如银行的网站)上的按钮,从而实现了在不知不觉中给攻击者转账的功能。

开发中间件:

定义方式:定义一个中间件工厂函数,然后返回一个可以被调用的中间件。中间件工厂函数需要接收一个可以调用的get_response对象。返回的中间件也是一个可以被调用的对象,并且像视图一样需要接受一个request对象参数,返回一个response对象。

step1:新建一个py文件用于定义中间件,如在子应用lq中。

step2:在该新建的py文件中定义中间件

step3:在settings文件中将自定义的中间件注册。格式:'子应用名.中间件py文件名.外函数名'即中间件的python路径

中间件的调用顺序:在请求视图被处理前,中间件由上至下依次执行,在请求视图被处理后,中间件由下至上依次执行。

理解:从外面回家,先进客厅,再进卧室;出去玩,先出卧室,再出客厅。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不懂编程的大学生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值