Django 的 View 里直接读写php 全局变量量安全么

如何在Django模板中注入全局变量
我们在做一些网站项目的时候,可能会遇到需要把某个全局变量注入到所有页面的情况,比如我们做一个在线商城,那么可能需要将用户的资料:比如用户的账号、用户的姓名等注入到每个页面里面。
TeamCola中每个页面右上角都会出现的用户名
但是如果用常规的方法,也就是在每个views方法中通过render_to_response方法注入用户数据的话,这样就会做非常多的重复工作,就像下面这样:
def views_meth1(request):
return render_to_response('template_1.html', {'user': request.user})
def views_meth2(request):
return render_to_response('template_2.html', {'user': request.user})
def views_meth3(request):
return render_to_response('template_3.html', {'user': request.user})
# ...剩下的N个方法
这在需要传入的变量比较简单、数量较少的时候还行,一旦需要注入的变量多一些,或是需要经过一些额外的计算才能生成的时候,那就麻烦大了。所以如何避免这种repeat yourself的2B模式呢?我们可以选择如下的一种模式:
在每次创建新的django项目的时候,一般来说我们都会在根目录中创建一个类似名为utils.py的工具module,在这个module中,我们可以通过定义一个自己的render方法,来为每次模板的渲染注入指定的全局变量:
# in utils.py:
def mp_render(request, template, context={}):
context['user'] = request.user
return render_to_response(template, context)
# in views.py:
from utils import mp_render
def views_meth1(request):
return mp_render(request, 'template_1.html')
def views_meth2(request):
return mp_render(request, 'template_2.html')
def views_meth3(request):
return mp_render(request, 'template_3.html')
很好理解吧,这样以后有新增加的全局变量需要注入的话,只需要修改mp_render方法就行了。嗯,这是很普通的方法,既然是普通方法,那就再来个文艺点的吧。
先来看看django文档里面对于吧,在’Required arguments’里面,有提到这个方法的第三个参数,叫context_instance,对于这个参数的说明如下:
The context instance to render the template with. By default, the template will be rendered with a Context instance (filled with values from dictionary). If you need to use context processors, render the template with a RequestContext instance instead. Your code might look something like this:
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
大意是:“默认的,render_to_response方法的第二个dictionary参数会被填充为一个Context对象注入进html模板文件里面。如果你需要使用context processors,那么需要使用一个RequestContext对象来渲染模板。”
那么什么是context processors呢?看完以后,应该一切就很明了了。
首先需要明白在django模板系统中,有两种封装模板变量的类,一个是django.template.Context,这是最常用的,我们在使用render_to_response方法的时候传入的第二个dictionary参数,就会被这个Context类封装一次,然后传到模板当中;另一个是django.template.RequestContext,它和Context类相比有两个不同之处。第一个不同的是,在生成一个RequestContext变量的时候,需要传入一个HttpRequest对象作为它的第一个参数:
c = RequestContext(request, {'foo': 'bar', })
第二个区别是,它会增加一些自动注入模板的变量,这些变量从哪儿来呢?在django的settings.py里有一部分是配置TEMPLATE_CONTEXT_PROCESSORS的,这个配置中的那一个个的tuple元素其实是一个个可以被调用的方法,而这些方法都会接收一个HttpRequest对象作为参数,而最终return一个dictionary,这个dictionary里面的元素就会成为RequestContext中自动注入模板的变量。我们看看settings.py中TEMPLATE_CONTEXT_PROCESSORS的某一个元素 django.contrib.auth.context_processors.auth 对应的代码吧:
# in django/contrib/auth/context_processors.py
def auth(request):
""" ignore doc string """
def get_user():
'user': SimpleLazyObject(get_user),
'messages': messages.get_messages(request),
lazy(lambda: PermWrapper(get_user()), PermWrapper)(),
可以看到,auth方法最后返回的一个字典中,包含了三个元素,所以如果在使用render_to_response方法时,传入了第三个RequestContext参数,那么在它所渲染的模板中,就可以获取到对应的user、messages、perms变量了。
所以最后文艺解决方法是,在每一个需要注入全局变量的views方法中,调用render_to_response的时候,都传入第三个RequestContext对象参数即可:
def views_meth1(request):
d1 = {'method': 1}
return render_to_response('template_1.html', d1, context_instance=RequestContext(request))
def views_meth2(request):
d2 = {'method': 2}
return render_to_response('template_2.html', d2, context_instance=RequestContext(request))
def views_meth3(request):
d3 = {'method': 3}
return render_to_response('template_2.html', d3, context_instance=RequestContext(request))
这样需要注入的全局对象,就可以通过扩展TEMPLATE_CONTEXT_PROCESSORS来实现,灵活性更高,更易扩展。当然,在一般的项目开发中,个人觉得普通方法也足够用,所以就根据项目来做取舍吧。
Copyright (C) , All Rights Reserved.
版权所有 闽ICP备号
processed in 0.051 (s). 10 q(s)安全检查中...
请打开浏览器的javascript,然后刷新浏览器
< 浏览器安全检查中...
还剩 5 秒&如何在Django模板中注入全局变量
如何在Django模板中注入全局变量
编辑:www.fx114.net
本篇文章主要介绍了"如何在Django模板中注入全局变量",主要涉及到如何在Django模板中注入全局变量方面的内容,对于如何在Django模板中注入全局变量感兴趣的同学可以参考一下。
刚开始接触django系统,难免遇到许多千奇百怪的问题,都是语法搞的,遇到一次就不会再犯了。
现在遇到的问题是,重写了django自带的登录方法,但登陆核心方法还是用的django自带的,只不过在外围做了一层封装,登录的时候认证可以通过,但在前台模板中却得不到user对象&#20540;,经一位大牛指导才知道,要想在模板中使用这些数据,必须先要用RequestContext渲染模板
从技术上来说,只有当你使用了RequestContext 并且 TEMPLATE_CONTEXT_PROCESSORS 设置包含了
&django.contrib.auth.context_processors.auth& (默认情况就是如此)时,这些变量才能在模板context中使用。
django.contrib.auth.context_processors.auth一般默认被加载,所以出现问题一定是因为没有使用RequestContext渲染模板。
主要就是为了共享数据,让某一变量变成全局变量,在所有页面都能访问到它。
具体操作步骤,参见:/system-analysis/036.html
我们在做一些网站项目的时候,可能会遇到需要把某个全局变量注入到所有页面的情况,比如我们做一个在线商城,那么可能需要将用户的资料:比如用户的账号、用户的姓名等注入到每个页面里面。
TeamCola中每个页面右上角都会出现的用户名
但是如果用常规的方法,也就是在每个views方法中通过render_to_response方法注入用户数据的话,这样就会做非常多的重复工作,就像下面这样:
def views_meth1(request):
return render_to_response('template_1.html', {'user': request.user})
def views_meth2(request):
return render_to_response('template_2.html', {'user': request.user})
def views_meth3(request):
return render_to_response('template_3.html', {'user': request.user})
# ...剩下的N个方法
这在需要传入的变量比较简单、数量较少的时候还行,一旦需要注入的变量多一些,或是需要经过一些额外的计算才能生成的时候,那就麻烦大了。所以如何避免这种repeat yourself的2B模式呢?我们可以选择如下的一种模式:
在每次创建新的django项目的时候,一般来说我们都会在根目录中创建一个类&#20284;名为utils.py的工具module,在这个module中,我们可以通过定义一个自己的render方法,来为每次模板的渲染注入指定的全局变量:
# in utils.py:
def mp_render(request, template, context={}):
context['user'] = request.user
return render_to_response(template, context)
# in views.py:
from utils import mp_render
def views_meth1(request):
return mp_render(request, 'template_1.html')
def views_meth2(request):
return mp_render(request, 'template_2.html')
def views_meth3(request):
return mp_render(request, 'template_3.html')
很好理解吧,这样以后有新增加的全局变量需要注入的话,只需要修改mp_render方法就行了。嗯,这是很普通的方法,既然是普通方法,那就再来个文艺点的吧。
先来看看django文档里面对于render_to_response这个方法的定义吧,在’Required arguments’里面,有提到这个方法的第三个参数,叫context_instance,对于这个参数的说明如下:
The context instance to render the template with. By default, the template will be rendered with a Context instance (filled with values from dictionary). If you need to use context processors, render the template with a RequestContext instance instead. Your
code might look something like this:
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
大意是:“默认的,render_to_response方法的第二个dictionary参数会被填充为一个Context对象注入进html模板文件里面。如果你需要使用context processors,那么需要使用一个RequestContext对象来渲染模板。”
那么什么是context processors呢?看完这一段文档的定义以后,应该一切就很明了了。
首先需要明白在django模板系统中,有两种封装模板变量的类,一个是django.template.Context,这是最常用的,我们在使用render_to_response方法的时候传入的第二个dictionary参数,就会被这个Context类封装一次,然后传到模板当中;另一个是django.template.RequestContext,它和Context类相比有两个不同之处。第一个不同的是,在生成一个RequestContext变量的时候,需要传入一个HttpRequest对象作为它的第一个参数:
c = RequestContext(request, {'foo': 'bar', })
第二个区别是,它会增加一些自动注入模板的变量,这些变量从哪儿来呢?在django的settings.py里有一部分是配置TEMPLATE_CONTEXT_PROCESSORS的,这个配置中的那一个个的tuple元素其实是一个个可以被调用的方法,而这些方法都会接收一个HttpRequest对象作为参数,而最终return一个dictionary,这个dictionary里面的元素就会成为RequestContext中自动注入模板的变量。我们看看settings.py中TEMPLATE_CONTEXT_PROCESSORS的某一个元素
django.contrib.auth.context_processors.auth 对应的代码吧:
# in django/contrib/auth/context_processors.py
def auth(request):
&&& ignore doc string &&&
def get_user():
'user': SimpleLazyObject(get_user),
'messages': messages.get_messages(request),
'perms': lazy(lambda: PermWrapper(get_user()), PermWrapper)(),
可以看到,auth方法最后返回的一个字典中,包含了三个元素,所以如果在使用render_to_response方法时,传入了第三个RequestContext参数,那么在它所渲染的模板中,就可以获取到对应的user、messages、perms变量了。
所以最后文艺解决方法是,在每一个需要注入全局变量的views方法中,调用render_to_response的时候,都传入第三个RequestContext对象参数即可:
def views_meth1(request):
d1 = {'method': 1}
return render_to_response('template_1.html', d1, context_instance=RequestContext(request))
def views_meth2(request):
d2 = {'method': 2}
return render_to_response('template_2.html', d2, context_instance=RequestContext(request))
def views_meth3(request):
d3 = {'method': 3}
return render_to_response('template_2.html', d3, context_instance=RequestContext(request))
这样需要注入的全局对象,就可以通过扩展TEMPLATE_CONTEXT_PROCESSORS来实现,灵活性更高,更易扩展。当然,在一般的项目开发中,个人觉得普通方法也足够用,所以就根据项目来做取舍吧。
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:1331人阅读
django(2)
对于django驱动网站的建议:
xss 保护:
xss攻击允许用户注入客户端脚本到其他用户的服务器上。通常通过存储恶意脚本到数据库,其他用户通过数据库获取恶意脚本,并在浏览器上呈现;或是使用户点击会引起攻击者javascirpt脚本在用户客户端的连接来达到目的。但是xss攻击可能发生在任意不可信的数据源头,例如cookie和web service。无论何时,只要数据在页面内没有充分地消毒(sanitized),就可能发生xss攻击。
用django的模板会保护你免受大部分xss攻击,但理解模板提供什么保护,和其局限性是十分重要的。
django 模板的转义对HTML危险的特殊字符。尽管这保护用户受到大多数恶意输入,但不是完全安全的。例如对下面的就不保护:
&styleclass={{var}}&...&/style&
如果var被赋'class1onmouseover=javascript:func()'&#20540;,这会导致未授权的Javascript执行,取决于浏览器怎样呈现未完成(imperfect)的HTML
当用到is_safe和自定义标签一起时(using is_safe with custom template tags),&#26684;外小心十分重要。
另外,如果你用模板输出非HTML的内容,完全分开的字符和单词需要转义。存储HTML到数据库时你同样应该小心,尤其是HTML被加载并展示的。
CSRF保护:
CSRF 攻击允许恶意用户用未经另一个用户知道或允许的证书执行动作。
django 内置了许多保护工作对抗大多数CSRF攻击,假如你已经在合适的地方开启并使用了。然而,像其他缓解技术一样有局限性。例如,全局或为某些特定视图禁止CSRF模块是可能的。只有你明白你在做什么时才能这样做。如果你的站点有在你控制范围之外的子域名时同样有其他限制。
CSRF保护的工作原理是检测每个POST请求的随机数。这确保了恶意用户不能简单地重放到你网站的表单的POST内容并让其他已经登录的用户不知不觉地提交那个表单。恶意用户需要知道那个随机数,而这个随机数是为特定用户(用cookie)
当用HTTPS部署时,CsrfViewMiddleware将会检查HTTP referer头被设定到同源域的URL(包括子域和端口)。因为HTTPS提供额外的安全,所以在转发不安全连接请求和可以用支持HSTS的浏览器的地方确保连接用HTTPS是很有必要的。
要非常小心地用csrf_exempt装饰器修饰视图,除非它绝对必要。
sql输入保护:
sql注入是一种恶意用户能够在数据库执行任意sql语句的攻击。这会导致记录被删除或数据泄露。
用django的queryset,以数据库驱动为基础,合成的(resulting)sql会被合适地转义。然而django同样给开发者权利写原始的查询或自定义的sql。这些能力应该被保守地使用。你应该一直小心去适当转义任何 用户可以控制的参数。另外,当用extra()时你更应该小心谨慎(exercise caution)
点击劫持保护:
点击劫持是恶意站点包围在另一个站点frame里的一种攻击。这种攻击能导致毫无戒心的用户被骗在目标站点上执行意想不到的行为。
django在X-Frame-Options 中间件的表单里包含有点击劫持保护功能,这种功能在支持的浏览器里可以保护站点不在frame里被渲染。可以按view的基础禁用这个保护功能,或配置发送明确的header。
强烈推荐任何一个不必要或是只允许小部分 使页面包装在第三方frame的网站 使用这个中间件。
ssl/https:
出于安全考虑,把你的网站部署成HTTPS总是更好的,尽管并不是所有情况都适用。没有HTTPS,恶意用户会嗅探身份认证信息,或者其他在客户端和服务器之间传输的信息。在某些案例中,活跃的攻击者会改变任一方传输的数据。
如果你想在你的服务器上开启HTTP,你需要做额外的步骤:
&&&&& 1、若必要,设置SECURE_PROXY_SSL_HEADER, 确保你彻底理解了警告。若不这样做会导致CSRF漏洞,若没有正确实施同样会导致危险。
&&&&& 2、建立跳转,基于HTTP的连接会跳转到HTTPS。
用自定义的中间件可以做到这些。请注意SECURE_PROXY_SSL_HEADER的警告。对于反向跳转的案例,配置主web 服务器做跳转到HTTPS会更简单和更安全
&&&&& 3、用安全的cookies
&&&&& 若浏览器用默认的HTTP连接,cookie会被泄露。所以需要你的 SESSION_COOKIE_SECURE 和CSRF_COOKIE_SECURE 设置为True。这会让浏览器只通过HTTPS传送cookies。注意着意味着session在HTTP下不会起作用,CSRF保护机制会阻止一切通过HTTP传送的POST数据。
&&&&& 4、用 HSTS(HTTP Strict Transport Security)
&&&&& HSTS是一个通知浏览器所有未来到某个站点的连接都用HTTPS的HTTP头部。通过组合 对请求从HTTP到HTTPS的跳转,确保了连接成功的连接总是能够使用SSL提供的安全保障。HSTS通常被部署在服务器上。
主机头确认
&&&&& 某些情况下,Django用客户端提供的host头来构建url。尽管这些&#20540;被过滤而组织XSS攻击,虚假的host&#20540;可能被用来实施CSRF,缓存投毒攻击,和邮件连接投毒。
&&&&& 因为看上去安全的服务器配置易受虚假host头欺骗,Django会在HttpRequest.get_host()方法中确认host 头是否与ALLOWED_HOSTS设置的&#20540;冲突。
&&&&& 确认只会由get_host()方法应用。若你的代码通过request.META直接访问host头,你会绕过这个安全防护。
&&&&& 需要更多的信息请参考ALLOWED_HOSTS部分。
&&&&& 另外,1.3.1版本的Django要求你明确开启对X-Forwarded-Host header的支持,如果你的配置需要的话
会话(session)安全:
&&&&& 和CSRF局限一样,需要对站点特殊配置使得不信任的用户没有权限访问子域,django.contrib.sessions同样有局限。参考 session topic guide on security获得更多信息。
用户上传内容:
&&&&& 若你的站点支持上传,强烈建议你配置限制上传文件的大小为合理的范围来防止拒绝服务攻击。在Apache下,用LimitRequestBody 指令很容易做到。
&&&&& 如果你自己管理你的静态文件,一定要关闭像Apache的mod_php一样的处理器,它们会把静态文件当成代码执行。你肯定不希望用户通过上传或请求精心制作的文件来执行任意代码。
&&&&& 当媒体没有遵循安全措施的最佳实践时,django 的媒体文件上传会造成某些漏洞。特别地,一个html文件会被当做文件上传,如果文件包含一个png头紧随其后的恶意的html代码。这个文件会通过django 的图像处理库的检查。当这个文件随后被展示给用户,根据你服务器的类型和配置,会被呈现为html。
&&&&& 在框架层面没有刀枪不入的验证所有用户上传的技术性的解决方案存在。但是你可以通过一些步骤减少这种攻击。
&&&&& 通过从一个独特的顶级或二级域名 serve用户上传的文件可以防止一类攻击。由于同源策略的保护,xss这类利用会被阻止。例如,你的站点在上,你可以把用户上传的文件映射到。而映射到是不够的。
&&&&& 应用还可以选择定义一个白名单,允许用户上传特定的扩展名的文件。
额外的安全策略:
&&&&& 尽管django提供了好的开箱即用的安全保护措施。正确部署你的应用,并利用好服务器操作系统和其他组件的安全也十分必要
&&&&& 确保你的python代码在服务器root文件夹之外,这确保了你的代码不被错误地解释为纯文本(或错误地被执行)
&&&&& 小心用户上传的文件
&&&&& django没有限制用以认证用户的请求。为防止暴力破解对认证系统的破坏,你可以考虑部署django的插件或web 服务器模块来限制这些请求。
&&&&& 保密你的SECRET_KEY
&&&&& 用防火墙限制对缓存系统和数据库的访问
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:12479次
排名:千里之外
原创:13篇
(1)(3)(4)(1)(2)(6)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'Django 设置template的全局变量 - 简书
Django 设置template的全局变量
相信许多Web开发者一定有那么一个需求,需要在所有的页面上面显示同样的后台数据。比如:
用户信息: 当一个用户登陆成功后肯定希望每个页面都能显示当前登陆用户的信息。
一些由后台生成的标签(或者说索引): 用户可以通过点击标签进行不同页面跳转,但是每个页面中都会有这些标签。
这个时候如果在view.py文件中的每一个方法里组织对应的数据用于页面解析,那绝对是十分蛋疼的事情,这个时候我们就需要把这些数据保存成全局变量的形式让他可以轻松渲染到每一个页面。Django
settings.py
文件里面有这样一个配置。
TEMPLATES = [
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, "templates")],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
注意到 OPTIONS.context_processors 里面有4条信息,其实每一条信息都对应一个函数,这里的原理是设置每一个函数的返回值作为Template的全局变量,而最简单的函数request他是这样的
from django.template import context_processors.py
def request(request):
return {'request': request}
它只是简单地返回一个字典 {'request': request} 这就不难理解为什么在Django的模板系统里面,所有的Template我们都可以直接访问request.user来获取对应的用户了吧。由于request被设置成全局变量,以字典的形式传到后台去了。
依样画葫芦,我们也可以编写个脚本。:
global_variable.py
from .models import Classification
from taggit.models import Tag
def setting(request):
classifications = Classification.objects.all()
tags = Tag.objects.all()
content = {"classifications": classifications, "tags": tags}
return content
这只是我blog系统的一小部分代码,用于获取所有的分类,以及所有的Tag标签,方便搜索。如果global_variable.py文件坐落在BASE_DIR(这个用过Django的朋友应该都知道了吧.这个变量是在settings.py文件里面)/blog/page目录下,则需要设置
settings.py
TEMPLATES = [
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, "templates")],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
# 加上这句
'blog.page.global_variable.setttings'
就OK 了,这样就可以在templates里面引用tags, 和classifications变量了.很感谢你有耐心看到这里,不过希望你能继续往下看,或许能对你有帮助.
你可能会遇到的坑
下面是我写的一段代码
def detail(request, id):
article = get_object_or_404(Article, pk=id)
template = loader.get_template("page/detail.html")
context = RequestContext(request, {'article': article})
return HttpResponse(template.render(context))
但是Django1.9给了我这样的提示RemovedInDjango110Warning: render() must be called with a dict, not a RequestContext.说10以后将会丢弃RequestContext理所当然,我把代码改成下面这样
def detail(request, id):
article = get_object_or_404(Article, pk=id)
template = loader.get_template("page/detail.html")
context = {'article': article}
return HttpResponse(template.render(context))
接着灾难就发生了,虽然说避开了1.9的警告,不过上面的代码,没有把request包装到RequestContext()里面解析到模板中去,这就会有一个问题.所有的settings里面设置的全局变量都不起作用了,他根本就不会去解析全局变量,这个坑,坑了我几个小时.所以最好的方法是采取Django给我们的偷懒方法.
from django.shortcuts import render
def detail(request, id):
article = get_object_or_404(Article, pk=id)
return render(request, "page/detail.html", context)
因为据说RequestContext()将在1.10被丢弃,考虑到兼容性,用它提供的接口最好不过啦.
记得一定要在view的方法里面把request传到后台哦,不然只传字典的话,全局变量那便会得不到解析的.
一位资质平庸的程序员。享受编码与生活。

我要回帖

更多关于 php 全局变量 的文章

 

随机推荐