VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > python爬虫 >
  • python全栈开发中Django的集成的子框架

Python有众多优点,其中之一就是“开机即用”原则:安装Python的同时安装好大量的标准软件包,这样 你可以立即使用而不用自己去下载。Django 遵循这个原则,它同样包含了自己的标准库。这一章就来讲 这些集成的子框架。

Django标准库

jango的标准库存放在 django.contrib 包中。每个子包都是一个独立的附加功能包。 它们互相之间一般没有必然的关联,但是有些 django.contrib 子包可能依赖其他的包。

在 django.contrib 中对函数的类型并没有强制要求 。其中一些包中带有模型(因此需要你在数据库中安装对应的数据表),但其它一些由独立的中间件及模板标签组成。

django.contrib 开发包共有的特性是:就算你将整个 django.contrib 开发包删除,你依然可以使用 Django 的基础功能而不会遇到任何问题。当 Django 开发者向框架增加新功能的时,他们会严格根据这一教条来决定是否把新功能放入 django.contrib中。

django.contrib 由以下开发包组成:

§ admin : 自动化的站点管理工具。请查看第6章和第18章

§ auth : Django的用户验证框架。请查看第12章

§ comments : 一个评论应用,目前,这个应用正在紧张的开发中,因此在本书出版的时候还不能给出一个完整的说明,关于这个应用的更多信息请参见Django的官方网站.

§ contenttypes : 这是一个用于文档类型钩子的框架,每个安装的Django模块作为一种独立的文档类型。这个框架主要在Django内部被其他应用使用,它主要面向Django的高级开发者。可以通过阅读源码来了解关于这个框架的更多信息,源码的位置在 django/contrib/contenttypes/ .

§ csrf : 这个模块用来防御跨站请求伪造(CSRF).参见后面标题为”CSRF 防御”的小节。

§ flatpages : 一个在数据库中管理单一HTML内容的模块,参见后面标题为“Flatpages”的小节。

§ humanize : 一系列 Django 模块过滤器,用于增加数据的人性化。参阅稍后的章节《人性化数据》。

§ markup : 一系列的 Django 模板过滤器,用于实现一些常用标记语言。参阅后续章节《标记过滤器》。

§ redirects : 用来管理重定向的框架。参见后面标题为《重定向》的小节。

§ sessions : Django 的会话框架,参见12章。

§ sitemaps : 用来生成网站地图的 XML 文件的框架。参见 11 章。

§ sites : 一个让你可以在同一个数据库与 Django 安装中管理多个网站的框架。参见下一节:站点。

§ syndication : 一个用 RSS 和 Atom 来生成聚合订阅源的的框架。参阅第 11 章。

本章接下来将详细描述前面没有介绍过的 django.contrib 开发包内容。

多个站点

Django 的多站点系统是一种通用框架,它让你可以在同一个数据库和同一个Django项目下操作多个网站。这是一个抽象概念,理解起来可能有点困难,因此我们从几个让它能派上用场的实际情景入手。

情景1:对多个站点重用数据

正如我们在第一章里所讲,Django 构建的网站 LJWorld.com 和 Lawrance.com 是用由同一个新闻组织控制的:肯萨斯州劳伦斯市的 劳伦斯日报世界 报纸。 LJWorld.com 主要做新闻,而 Lawrence.com 关注本地娱乐。然而有时,编辑可能需要把一篇文章发布到 两个 网站上。

解决此问题的死脑筋方法可能是使用每个站点分别使用不同的数据库,然后要求站点维护者把同一篇文章发布两次:一次为 LJWorld.com,另一次为Lawrence.com。但这对站点管理员来说是低效率的,而且为同一篇文章在数据库里保留多个副本也显得多余。

更好的解决方案?两个网站用的是同一个文章数据库,并将每一篇文章与一个或多个站点用多对多关系关联起来。Django 站点框架提供数据库记载哪些文章可以被关联。它是一个把数据与一个或多个站点关联起来的钩子。

情景2:把你的网站名称/域存储到唯一的位置

LJWorld.com 和 Lawrence.com 都有邮件提醒功能,使读者注册后可以在新闻发生后立即收到通知。这是一种完美的的机制:某读者提交了注册表单,然后马上就受到一封内容是“感谢您的注册”的邮件。

把这个注册过程的代码实现两遍显然是低效、多余的,因此两个站点在后台使用相同的代码。但感谢注册的通知在两个网站中需要不同。通过使用 Site 对象,我们通过使用当前站点的 name (例如 'LJWorld.com' )和 domain (例如 'www.ljworld.com' )可以把感谢通知抽提出来。

Django 的多站点框架为你提供了一个位置来存储 Django 项目中每个站点的 name 和 domain ,这意味着你可以用同样的方法来重用这些值。

如何使用多站点框架

多站点框架与其说是一个框架,不如说是一系列约定。所有的一切都基于两个简单的概念:

§ 位于 django.contrib.sites 的 Site 模型有 domain 和 name 两个字段。

§ SITE_ID 设置指定了与特定配置文件相关联的 Site 对象之数据库 ID。

如何运用这两个概念由你决定,但 Django 是通过几个简单的约定自动使用的。

安装多站点应用要执行以下几个步骤:

  1. 将 'django.contrib.sites' 加入到 INSTALLED_APPS 中。

  2. 运行 manage.py syncdb 命令将 django_site 表安装到数据库中。

  3. 通过 Django 管理后台或通过 Python API 添加一个或者多个 ‘Site’ 对象。为该 Django 项目支撑的每个站(或域)创建一个 Site 对象。

  4. 在每个设置文件中定义一个 SITE_ID 变量。该变量值应当是该设置文件所支撑的站点之 Site 对象的数据库 ID 。

多站点框架的功能

下面几节讲述的是用多站点框架能够完成的几项工作。

多个站点的数据重用

正如在情景一中所解释的,要在多个站点间重用数据,仅需在模型中为 Site 添加一个 多对多字段 即可,例如:

 from django.db import models

 from django.contrib.sites.models import Site



 class Article(models.Model):

     headline = models.CharField(maxlength=200)

     # ...

     sites = models.ManyToManyField(Site)

这是在数据库中为多个站点进行文章关联操作的基础步骤。在适当的位置使用该技术,你可以在多个站点中重复使用同一段 Django 视图代码。继续 Article 模型范例,下面是一个可能的 article_detail 视图:

 from django.conf import settings



 def article_detail(request, article_id):

     try:

         a = Article.objects.get(id=article_id, sites__id=settings.SITE_ID)

     except Article.DoesNotExist:

         raise Http404

     # ...

该视图方法是可重用的,因为它根据 SITE_ID 设置的值动态检查 articles 站点。

例如, LJWorld.coms 设置文件中有有个 SITEID 设置为 1 ,而 Lawrence.coms 设置文件中有个 SITEID 设置为 2 。如果该视图在 LJWorld.coms 处于激活状态时被调用,那么它将把查找范围局限于站点列表包括 LJWorld.com 在内的文章。

将内容与单一站点相关联

同样,你也可以使用 外键 在多对一关系中将一个模型关联到 Site 模型。

举例来说,如果某篇文章仅仅能够出现在一个站点上,你可以使用下面这样的模型:

 from django.db import models

 from django.contrib.sites.models import Site



 class Article(models.Model):

     headline = models.CharField(maxlength=200)

     # ...

     site = models.ForeignKey(Site)

这与前一节中介绍的一样有益。

从视图钩挂当前站点

在底层,通过在 Django 视图中使用多站点框架,你可以让视图根据调用站点不同而完成不同的工作,例如:

 from django.conf import settings



 def my_view(request):

     if settings.SITE_ID == 3:

         # Do something.

     else:

         # Do something else.

当然,像那样对站点 ID 进行硬编码是比较难看的。略为简洁的完成方式是查看当前的站点域:

 from django.conf import settings

 from django.contrib.sites.models import Site



 def my_view(request):

     current_site = Site.objects.get(id=settings.SITE_ID)

     if current_site.domain == 'foo.com':

         # Do something

     else:

         # Do something else.

从 Site 对象中获取 settings.SITEID 值的做法比较常见,因此 Site 模型管理器 (Site.objects ) 具备一个 getcurrent() 方法。下面的例子与前一个是等效的:

 from django.contrib.sites.models import Site



 def my_view(request):

     current_site = Site.objects.get_current()

     if current_site.domain == 'foo.com':

         # Do something

     else:

         # Do something else.

注意

在这个最后的例子里,你不用导入 django.conf.settings 。

获取当前域用于呈现

正如情景二中所解释的那样,对于储存站名和域名的 DRY (Dont Repeat Yourself) 方法(在一个位置储存站名和域名)来说,只需引用当前 Site 对象的 name 和 domain 。例如:

 from django.contrib.sites.models import Site

 from django.core.mail import send_mail



 def register_for_newsletter(request):

     # Check form values, etc., and subscribe the user.

     # ...

     current_site = Site.objects.get_current()

     send_mail('Thanks for subscribing to %s alerts' % current_site.name,

         'Thanks for your subscription. We appreciate it.\n\n-The %s team.' % current_site.name,

         'editor@%s' % current_site.domain,

         [user_email])

     # ...

继续我们正在讨论的 LJWorld.com 和 Lawrence.com 例子,在Lawrence.com 该邮件的标题行是“感谢注册 Lawrence.com 提醒信件”。在 LJWorld.com ,该邮件标题行是“感谢注册 LJWorld.com 提醒信件”。这种站点关联行为方式对邮件信息主体也同样适用。

完成这项工作的一种更加灵活(但重量级也更大)的方法是使用 Django 的模板系统。假定 Lawrence.com 和 LJWorld.com 各自拥有不同的模板目录( TEMPLATE_DIRS ),你可将工作轻松地转交给模板系统,如下所示:

 from django.core.mail import send_mail

 from django.template import loader, Context



 def register_for_newsletter(request):

     # Check form values, etc., and subscribe the user.

     # ...

     subject = loader.get_template('alerts/subject.txt').render(Context({}))

     message = loader.get_template('alerts/message.txt').render(Context({}))

     send_mail(subject, message, 'do-not-reply@example.com', [user_email])

     # ...

本例中,你不得不在 LJWorld.com 和 Lawrence.com 的模板目录中都创建一份 subject.txt 和 message.txt 模板。正如之前所说,该方法带来了更大的灵活性,但也带来了更多复杂性。

尽可能多的利用 Site 对象是减少不必要的复杂、冗余工作的好办法。

获取当前域的完整 URL

Django 的 getabsoluteurl() 约定对与获取不带域名的对象 URL 非常理想,但在某些情形下,你可能想显示某个对象带有http:// 和域名以及所有部分的完整 URL 。要完成此工作,你可以使用多站点框架。下面是个简单的例子:

 >>> from django.contrib.sites.models import Site

 >>> obj = MyModel.objects.get(id=3)

 >>> obj.get_absolute_url()

 '/mymodel/objects/3/'

 >>> Site.objects.get_current().domain

 'example.com'

 >>> 'http://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url())

 'http://example.com/mymodel/objects/3/'

当前站点管理器

如果 站点 在你的应用中扮演很重要的角色,请考虑在你的模型中使用方便的 CurrentSiteManager 。这是一个模型管理器(见附录B),它会自动过滤使其只包含与当前 站点 相关联的对象。

通过显示地将 CurrentSiteManager 加入模型中以使用它。例如:

 from django.db import models

 from django.contrib.sites.models import Site

 from django.contrib.sites.managers import CurrentSiteManager



 class Photo(models.Model):

     photo = models.FileField(upload_to='/home/photos')

     photographer_name = models.CharField(maxlength=100)

     pub_date = models.DateField()

     site = models.ForeignKey(Site)

     objects = models.Manager()

     on_site = CurrentSiteManager()

通过该模型,Photo.objects.all() 将返回数据库中所有的 Photo 对象,而 Photo.onsiteall() 仅根据 SITE_ID 设置返回与当前站点相关联的 Photo 对象。

换言之,以下两条语句是等效的:

 Photo.objects.filter(site=settings.SITE_ID)

 Photo.on_site.all()

CurrentSiteManager 是如何知道 Photo 的哪个字段是 Site 呢?缺省情况下,它会查找一个叫做site 的字段。如果模型中有个 外键 或 多对多字段 叫做 site 之外 的名字,你必须显示地将它作为参数传递给 CurrentSiteManager 。下面的模型中有个叫做 publish_on 的字段,如下所示:

 from django.db import models

 from django.contrib.sites.models import Site

 from django.contrib.sites.managers import CurrentSiteManager



 class Photo(models.Model):

     photo = models.FileField(upload_to='/home/photos')

     photographer_name = models.CharField(maxlength=100)

     pub_date = models.DateField()

     publish_on = models.ForeignKey(Site)

     objects = models.Manager()

     on_site = CurrentSiteManager('publish_on')

如果试图使用 CurrentSiteManager 并传入一个不存在的字段名, Django 将引发一个 ValueError 异常。

注意事项

即便是已经使用了 CurrentSiteManager ,你也许还想在模型中拥有一个正常的(非站点相关)的 管理器 。正如在附录 B 中所解释的,如果你手动定义了一个管理器,那么 Django 不会为你创建全自动的 objects = models.Manager() 管理器。

同样,Django 的特定部分——即 Django 超级管理站点和通用视图——使用的管理器 首先 在模型中定义,因此如果希望超级管理站点能够访问所有对象(而不是仅仅站点特有对象),请于定义 CurrentSiteManager 之前在模型中放入objects = models.Manager() 。

Django如何使用多站点框架

尽管并不是必须的,我们还是强烈建议使用多站点框架,因为 Django 在几个地方利用了它。即使只用 Django 来支持单个网站,你也应该花一点时间用 domain 和 name 来创建站点对象,并将 SITE_ID 设置指向它的 ID 。

以下讲述的是 Django 如何使用多站点框架:

§ 在重定向框架中(见后面的重定向一节),每一个重定向对象都与一个特定站点关联。当 Django 搜索重定向的时候,它会考虑当前的 SITE_ID 。

§ 在注册框架中,每个注释都与特定站点相关。每个注释被张贴时,其 site 被设置为当前的 SITE_ID ,而当通过适当的模板标签列出注释时,只有当前站点的注释将会显示。

§ 在 flatpages 框架中 (参见后面的 Flatpages 一节),每个 flatpage 都与特定的站点相关联。创建 flatpage 时,你都将指定它的 site ,而 flatpage 中间件在获取 flatpage 以显示它的过程中,将查看当前的 SITE_ID 。

§ 在 syndication 框架中(参阅第 11 章), title 和 description 的模板自动访问变量 {{ site }} ,它就是代表当前着桨的 Site 对象。Also, the hook for providing item URLs will use the domain from the current Site object if you dont specify a fully qualified domain.

§ 在身份验证框架(参见第 12 章)中, django.contrib.auth.views.login 视图将当前 Site 名称作为 {{ site_name }} 传递给模板。

Flatpages - 简单页面

尽管通常情况下总是建造和运行数据库驱动的 Web 应用,你还是会需要添加一两张一次性的静态页面,例如“关于”页面,或者“隐私策略”页面等等。可以用像 Apache 这样的标准Web服务器来处理这些静态页面,但却会给应用带来一些额外的复杂性,因为你必须操心怎么配置 Apache,还要设置权限让整个团队可以修改编辑这些文件,而且你还不能使用 Django 模板系统来统一这些页面的风格。

这个问题的解决方案是使用位于 django.contrib.flatpages 开发包中的 Django 简单页面(flatpages)应用程序。该应用让你能够通过 Django 超级管理站点来管理这些一次性的页面,还可以让你使用 Django 模板系统指定它们使用哪个模板。它在后台使用了 Django 模型,也就是说它将页面存放在数据库中,你也可以像对待其他数据一样用标准 Django 数据库 API 存取简单页面。

简单页面以它们的 URL 和站点为键值。当创建简单页面时,你指定它与哪个URL以及和哪个站点相关联 。(有关站点的更多信息,请查阅《站点》一节)

使用简单页面

安装平页面应用程序必须按照下面的步骤:

  1. 添加 'django.contrib.flatpages' 到 INSTALLED_APPS 设置。 django.contrib.flatpages 依赖于 django.contrib.sites , 所以确保这两个开发包都包括在INSTALLED_APPS 设置中。

  2. 将 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' 添加到 MIDDLEWARE_CLASSES 设置中。

  3. 运行 manage.py syncdb 命令在数据库中创建必需的两个表。

简单页面应用程序在数据库中创建两个表: djangoflatpage 和 djangoflatpagesites 。 djangoflatpage 只是将 URL 映射到到标题和一段文本内容。 djangoflatpagesites 是一个多对多表,用于关联某个简单页面以及一个或多个站点。

该应用所带来的 FlatPage 模型在 django/contrib/flatpages/models.py 进行定义,如下所示:

 from django.db import models

 from django.contrib.sites.models import Site



 class FlatPage(models.Model):

     url = models.CharField(maxlength=100)

     title = models.CharField(maxlength=200)

     content = models.TextField()

     enable_comments = models.BooleanField()

     template_name = models.CharField(maxlength=70, blank=True)

     registration_required = models.BooleanField()

     sites = models.ManyToManyField(Site)

让我们逐项看看这些字段的含义:

§ url : 该简单页面所处的 URL,不包括域名,但是包含前导斜杠 (例如 /about/contact/ )。

§ title : 简单页面的标题。框架不对它作任何特殊处理。由你通过模板来显示它。

§ content : 简单页面的内容 (即 HTML 页面)。框架不会对它作任何特别处理。由你负责使用模板来显示。

§ enable_comments : 是否允许该简单页面使用注释。框架不对此做任何特别处理。你可在模板中检查该值并根据需要显示注释窗体。

§ template_name : 用来解析该简单页面的模板名称。这是一个可选项;如果未指定模板或该模板不存在,系统会退而使用默认模板 flatpages/default.html 。

§ registration_required : 是否注册用户才能查看此简单页面。该设置项集成了 Djangos 验证/用户框架,该框架将于第十二章详述。

§ sites : 该简单页面放置的站点。该项设置集成了 Django 多站点框架,该框架在本章的《多站点》一节中有所阐述。

你可以通过 Django 超级管理界面或者 Django 数据库 API 来创建平页面。要了解更多内容,请查阅《添加、修改和删除简单页面》一节。

一旦简单页面创建完成, FlatpageFallbackMiddleware 将完成(剩下)所有的工作。每当 Django 引发 404 错误,作为终极手段,该中间件将根据所请求的 URL 检查平页面数据库。确切地说,它将使用所指定的 URL以及 SITE_ID 设置对应的站点 ID 查找一个简单页面。

如果找到一个匹配项,它将载入该简单页面的模板(如果没有指定的话,将使用默认模板 flatpages/default.html )。同时,它把一个简单的上下文变量—— flatpage (一个简单页面对象)传递给模板。在模板解析过程中,它实际用的是 RequestContext。

如果 FlatpageFallbackMiddleware 没有找到匹配项,该请求继续如常处理。

注意

该中间件仅在发生 404 (页面未找到)错误时被激活,而不会在 500 (服务器错误)或其他错误响应时被激活。还要注意的是必须考虑 MIDDLEWARE_CLASSES 的顺序问题。通常,你可以把 FlatpageFallbackMiddleware 放在列表最后,因为它是一种终极手段。

添加、修改和删除简单页面

可以用两种方式增加、变更或删除简单页面:

通过超级管理界面

如果已经激活了自动的 Django 超级管理界面,你将会在超级管理页面的首页看到有个 Flatpages 区域。你可以像编辑系统中其它对象那样编辑简单页面。

通过 Python API

前面已经提到,简单页面表现为 django/contrib/flatpages/models.py 中的标准 Django 模型。因此,你可以通过 Django 数据库 API 来存取简单页面对象,例如:

 >>> from django.contrib.flatpages.models import FlatPage

 >>> from django.contrib.sites.models import Site

 >>> fp = FlatPage(

 ...     url='/about/',

 ...     title='About',

 ...     content='<p>About this site...</p>',

 ...     enable_comments=False,

 ...     template_name='',

 ...     registration_required=False,

 ... )

 >>> fp.save()

 >>> fp.sites.add(Site.objects.get(id=1))

 >>> FlatPage.objects.get(url='/about/')

 <FlatPage: /about/ -- About>

使用简单页面模板

缺省情况下,系统使用模板 flatpages/default.html 来解析简单页面,但你也可以通过设定 FlatPage 对象的 template_name 字段来覆盖特定简单页面的模板。

你必须自己创建 flatpages/default.html 模板。只需要在模板目录创建一个 flatpages 目录,并把 default.html 文件置于其中。

简单页面模板只接受有一个上下文变量—— flatpage ,也就是该简单页面对象。

以下是一个 flatpages/default.html 模板范例:

 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"

     "http://www.w3.org/TR/REC-html40/loose.dtd">

 <html>

 <head>

 <title>{{ flatpage.title }}</title>

 </head>

 <body>

 {{ flatpage.content }}

 </body>

 </html>

重定向

通过将重定向存储在数据库中并将其视为 Django 模型对象,Django 重定向框架让你能够轻松地管理它们。比如说,你可以通过重定向框架告诉Django,把任何指向 /music/ 的请求重定向到 /sections/arts/music/ 。当你需要在站点中移动一些东西时,这项功能就派上用场了——网站开发者应该穷尽一切办法避免出现坏链接。

使用重定向框架

安装重定向应用程序必须遵循以下步骤:

  1. 将 'django.contrib.redirects' 添加到 INSTALLED_APPS 设置中。

  2. 将 'django.contrib.redirects.middleware.RedirectFallbackMiddleware' 添加到 MIDDLEWARE_CLASSES 设置中。

  3. 运行 manage.py syncdb 命令将所需的表安装到数据库中。

manage.py syncdb 在数据库中创建了一个 djangoredirect 表。这是一个简单的查询表,只有 siteid 、 oldpath 和 newpath三个字段。

你可以通过 Django 超级管理界面或者 Django 数据库 API 来创建重定向。要了解更多信息,请参阅《增加、变更和删除重定向》一节。

一旦创建了重定向, RedirectFallbackMiddleware 类将完成所有的工作。每当 Django 应用引发一个 404 错误,作为终极手段,该中间件将为所请求的 URL 在重定向数据库中进行查找。确切地说,它将使用给定的 oldpath 以及 SITEID 设置对应的站点 ID 查找重定向设置。(查阅前面的《多站点》一节可了解关于 SITE_ID 和多站点框架的更多细节) 然后,它将执行以下两个步骤:

§ 如果找到了匹配项,并且 newpath 非空,它将重定向到 newpath 。

§ 如果找到了匹配项,但 new_path 为空,它将发送一个 410 (Gone) HTTP 头信息以及一个空(无内容)响应。

§ 如果未找到匹配项,该请求将如常处理。

该中间件仅为 404 错误激活,而不会为 500 错误或其他任何状态码的响应所激活。

注意必须考虑 MIDDLEWARE_CLASSES 的顺序。通常,你可以将 RedirectFallbackMiddleware 放置在列表的最后,因为它是一种终极手段。

注意

如果同时使用重定向和简单页面回退中间件, 必须考虑先检查其中的哪一个(重定向或简单页面)。我们建议将简单页面放在重定向之前(因此将简单页面中间件放置在重定向中间件之前),但你可能有不同想法。

增加、变更和删除重定向

你可以两种方式增加、变更和删除重定向:

通过超级管理界面

如果已经激活了全自动的 Django 超级管理界面,你应该能够在超级管理首页看到重定向区域。可以像编辑系统中其它对象一样编辑重定向。

通过 Python API

django/contrib/redirects/models.py 中的一个标准 Django 模型代表了重定向。因此,你可以通过 Django 数据库 API 来存取重定向对象,例如:

 >>> from django.contrib.redirects.models import Redirect

 >>> from django.contrib.sites.models import Site

 >>> red = Redirect(

 ...     site=Site.objects.get(id=1),

 ...     old_path='/music/',

 ...     new_path='/sections/arts/music/',

 ... )

 >>> red.save()

 >>> Redirect.objects.get(old_path='/music/')

 <Redirect: /music/ ---> /sections/arts/music/>

CSRF 防护

django.contrib.csrf 开发包能够防止遭受跨站请求伪造攻击 (CSRF).

CSRF, 又叫进程跳转,是一种网站安全攻击技术。当某个恶意网站在用户未察觉的情况下将其从一个已经通过身份验证的站点诱骗至一个新的 URL 时,这种攻击就发生了,因此它可以利用用户已经通过身份验证的状态。开始的时候,要理解这种攻击技术比较困难,因此我们在本节将使用两个例子来说明。

一个简单的 CSRF 例子

假定你已经登录到 example.com 的网页邮件账号。该网页邮件站点上有一个登出按钮指向了 URL example.com/logout ,换句话说,要登出的话,需要做的唯一动作就是访问 URL : example.com/logout 。

通过在(恶意)网页上用隐藏一个指向 URL example.com/logout 的 



相关教程