标签:有序 程序 pytho 没有 cross protect href roc def
目录
? 由于http协议是无状态的,每次请求都是独立的,当用户访问浏览器网页时,并不会记录登录状态,所以,对服务器来说,你的每次请求都是全新的。
? 那么,为了保存用户的登录状态以及信息,就有了cookie,cookie具体指的是一段小信息,他是服务器大宋出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用的信息。
? 由服务器产生内容,浏览器收到请求后保存在本地,当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容判断当前用户信息了。
? F12打开浏览器开发者工具,在Aplication选项里的cookies能看到当前页面存储的cookies。
request.COOKIES.get()
首先,你需要将页面返回的内容交给一个变量接收
? obj = HttpResponse()
? obj = render()
? obj = redirect()
然后就可以通过这个对象来设置cookie,最后返回这个对象即可。
obj.set_cookie(‘k‘:‘v‘...)
同样需要用对象来操作。
obj.delete_cookie(‘key‘)
def login_auth(func):
@wraps(func)
def inner(request,*args,**kwargs):
if request.COOKIES.get('name'):
res = func(request,*args,**kwargs)
return res
else:
target_url = request.path_info
return redirect('/login/?next=%s'%target_url)
return inner
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'shabi' and password == '123':
old_path = request.GET.get('next')
if old_path:
obj = redirect(old_path)
else:
obj = redirect('/home/')
obj.set_cookie('name','shabi')
return obj
return render(request,'login.html')
@login_auth
def home(request):
'''模拟主页'''
return HttpResponse('我是主页,只有登录之后才能看!')
@login_auth
def logout(request):
'''注销'''
obj = redirect('/login/')
obj.delete_cookie('name')
return obj
? cookie虽然在一定程度上解决了保持状态的需求,但是由于cookie本身最大支持4096字节,以及cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新东西,它能支持更多的字节,并且还能保存在服务器上,有较高的安全性,这就是session。
request.session[‘key‘] = value
仅仅只会在内存中产生一个缓存,内部发生了三件事:
request.session.get(‘key‘)
内部也发生了三件事:
request.session.delete()
:只删除服务端的session
request.session.flush()
:浏览器和服务端的session会被全部清除
request.session.set_expiry(value)
value值:
from django import forms
class Myform(forms.Form):
username = forms.CharField(max_length=8,min_length=3)
password = forms.CharField(max_length=8,min_length=3)
def login(request):
form_obj = Myform()
if request.method == 'POST':
form_obj = Myform(request.POST)
if form_obj.is_valid():
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'nick' and password == '123':
old_path = request.GET.get('next')
request.session['user'] = username
if old_path:
obj = redirect(old_path)
else:
obj = HttpResponse('登录成功')
# obj.set_cookie('name','nick')
return obj
return render(request,'login.html',locals())
from functools import wraps
def login_auth(func):
@wraps(func)
def inner(request,*args,**kwargs):
# if request.COOKIES.get('name'):
if request.session.get('user'):
res = func(request,*args,**kwargs)
return res
else:
target_url = request.path_info
return redirect('/login/?next=%s'%target_url)
return inner
@login_auth
def home(request):
return HttpResponse('home')
@login_auth
def index(request):
return HttpResponse('index')
@login_auth
def logout(request):
request.session.delete()
return HttpResponse('注销成功!')
利用forms组件实现页面渲染以及数据校验
<form action="" method="post" novalidate>
{% csrf_token %}
{% for foo in form_obj %}
<p>{{ foo.label }}:{{ foo }}</p>
<span style="color: red">{{ foo.errors.0 }}</span>
{% endfor %}
<input type="submit">
</form>
注意:
? 中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量,低级别的插件系统,用在于全局范围内概念Django的输入和输出。每个中间件组件都负责做一些特定的功能。
? 但是由于其影响的是全局,所以需要谨慎使用,使用不当会影响性能。
? 其实,中间件的实质就是在视图函数执行前后自动执行的一系列额外的操作。本质就是一个自定义类,类中定义了几个方法。
? 打开Django项目的Settings.py文件,里面就存放着MIDDLEWARE配置,这就是中间件。它是以列表存储的几个字符串,这些字符串就是存放特定功能的中间件类的路径。我们也可以自定义中间件,只需将路径以字符串的形式在MIDDLEWARE中注册一下就可以了。
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',
]
注意:
? Django中间件暴露给程序员五个可以自定义的方法,这五个方法都是特定条件下自动触发的。
? 新建一个文件夹,里面新建一个任意名称的py文件,里面写类,固定继承。
from django.utils.deprecation import MiddlewareMixin
class MyMiddle(MiddlewareMixin):
def process_request(self,request):
'''
请求来的时候,会自上而下依次经过每一个中间件里面的process_request。
一旦里面返回了一个HttpResponse对象,那么就不再往后执行了。
之后会执行同一级别的process_response。
'''
pass
def process_response(self,request,response):
'''
响应走的时候,会自下而上依次经过每个中间件里面的process_response。
此方法必须将response返回出去,因为这个response就是返回给用户的数据。
'''
pass
return response
def process_view(self,request,view_func,view_args,view_kwargs):
'''
路由匹配成功之后|执行视图函数之前触发
'''
pass
def process_exception(self,request,exception):
'''
当视图函数出现异常的时候自动触发
'''
pass
def process_template_response(self,request,response):
'''
当视图函数执行完毕之后,并且返回的对象中含有render方法的情况下才会触发。
'''
pass
return response
? 然后去配置文件中手动注册:‘app01.mymiddleware.myaabb.MyMiddle1‘
? 伪造与真实的网站一模一样的web页面,比如,当你访问这个钓鱼网站中,页面会给你一个自定义个表单,比如转账,会给你暴露一个没有name属性的input框,取而代之的是提前写好的一个隐藏的带有name和value的input框,这样,你输入的数据就会被钓鱼网站非法篡改,并且会提交到真实的网站中。
? 只要是用户想要提交post请求的页面,我在返回给用户响应的时候就提前设置好一个随机字符串,当用户提交post请求的时候,会自动先取查找是否有该随机字符串。
? 如果有,正常提交,没有的话,直接403拒绝访问(CsrfViewMiddleware)
? 当你提交post请求时,CsrfViewMiddleware中间件就会校验你的post请求有没有一个随机字符串,没有的话会直接给你forbidden。针对不同的情况,有不同的解决方法。
? 在form表单中添加csrf_token
<form action="" method="post">
{% csrf_token %}
{% for foo in form_obj %}
<p>{{ foo.label }}:{{ foo }}</p>
{% endfor %}
<input type="submit">
</form>
在html页面上先通过{% csrf_token %}获取到随机字符串,然后利用标签来查找。
data:{‘username‘:‘zzz‘,‘csrfmiddlewaretoken‘:$(‘[name="csrfmiddlewaretoken"]‘).val()}
data:{‘username‘:‘jason‘,‘csrfmiddlewaretoken‘:‘{{ csrf_token }}‘}
? 这种方式只适合能提供csrf_token的python的Django后端,当前后端完全分离之后,前端也不支持Django的模板语法了,所以,这种方式在前后端分离之后不适用。
通过Django官网的官方js文档来实现。
<script src="/static/setup.js"></script>
// 官方js文档
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
from django.views.decorators.csrf import csrf_exempt, csrf_protect
两个装饰器:
直接在被装饰函数加装饰器即可
@csrf_exempt
def exem(request):
return HttpResponse('exempt')
@csrf_protect
def pro(request):
return HttpResponse('pro')
需要用到method_decorator装饰器
from django.views import View
from django.views.decorators.csrf import csrf_exempt, csrf_protect
# 第一种
# @method_decorator(csrf_exempt,name='dispatch')
@method_decorator(csrf_protect,name='post')
class MyCsrf(View):
# 第二种
# @method_decorator(csrf_exempt)
@method_decorator(csrf_protect)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return HttpResponse('hahaha')
@method_decorator(csrf_protect)
def post(self,request):
return HttpResponse('post')
"""
method_decorator()
指定了两个参数,第一个放装饰器名称,第二个放被装饰的函数名
如果放在类之外,必须指定name为类中的哪个方法。
如果直接放在函数中,可以不指定name参数。
"""
标签:有序 程序 pytho 没有 cross protect href roc def
原文地址:https://www.cnblogs.com/dadazunzhe/p/11768214.html