标签:www 过期 是什么 reg password encrypt 服务端 data backend
上课第19天,打卡:
忠于你的理想,别想生活妥协,让挣扎变得有意义!
################
# 2017-09-03 - 课上笔记
################
class day19:
def __init__():
pass
def do_homework():
pass
def do_my_project():
pass
‘‘‘Django 回顾‘‘‘
- http请求周期
浏览器(socket客户端)
2.socket.connect(ip,port) 进行连接
3.socket.send("http://www.qq.com/index.html...") url + data
遵循的规则:http协议
请求头
请求体
请求头和请求体使用 ‘\r\n\r\n‘ 分隔,前面是请求头,后面是请求体
GET请求: "GET /index.html?key=1... Http/1.1\r\nhost:www.qq.com\r\ncontent-type:application/json\r\n\r\n"
POST请求:"POST /index.html Http/1.1\r\nhost:www.qq.com\r\ncontent-type:application/json\r\n\r\nname=alex&pwd=123"
6.获取响应
响应头,响应体 = data.split("\r\n\r\n")
响应头之间用 ‘\r\n‘ 分隔
7.断开连接
nginx(socket服务端)
1.server.run(),监听IP和PORT
4.server.recv()
请求头,请求体 = data.split("\r\n\r\n")
request.POST.get(‘name‘) 即是从 请求体 里取值
5.服务端进行响应:
conn.send(‘......‘)
遵循的规则:http协议
响应头
响应体
7.断开连接
总结:
a.Http请求中本质都是字符串
b.Http请求是短连接(请求 -> 响应 -> 断开连接)
c.请求和响应都有头和体
请求:请求头‘\r\n\r\n‘请求体
响应:响应头‘\r\n\r\n‘响应体
由于需要处理繁琐http的解析和封装处理工作,所以web框架应运而生
web框架
- Django
socket(wsgiref) django没有自己写socket
解析和封装http请求
django-admin startproject mysite
cd mysite
python manage.py startapp app01
coding...(*****)
python manage.py runserver ip:port
‘‘‘写代码‘‘‘
- 路由系统
/login/ func name=‘f1‘
/login/\d+/ func name=‘f2‘
/login/(?P<n>\d+)/ func name=‘f3‘
/login/\d+/ include(‘app01.urls‘)
- 视图函数
def index(request):
request.GET
request.body 原生的请求体
request.POST 转换后的请求体字典 如果请求头中content-type=urlencode-form... 才将request.body转换成字典
- 可能有值
- 也可能没有值
request.method
request.Meta
request.GET.get()
request.GET.getlist() 前端多选的情况,如多个作者
request.POST.get()
request.POST.getlist()
return HttpResponse(‘字符串/字节‘)
return render(request,"html路径",locals())
return redirect("url")
- 模板
for if
继承
filter,simple_tag
- Models操作
- 创建表
- models.xxx.objects.create(name="xxxx")
- models.xxx.objects.create(**dic)
- models.xxx.objects.filter(id__gt=1).delete()
- models.xxx.objects.filter(id=1)
- models.xxx.objects.exclude(id=5) 取出id不等于5的
- models.xxx.objects.filter(id=1).update(name=‘ddd‘)
- models.xxx.objects.filter(id=1).update(**dic)
queryset --> [对象,对象...]
objs = models.xxx.objects.all()
queryset --> [{},{}...]
objs = models.xxx.objects.all().values()
queryset --> [(),()...]
objs = models.xxx.objects.all().values_list()
demo1
业务线表 bussiness_unit
id name
主机表 serverinfo
id host port bs(业务线对象)
objs = modesl.serverinfo.objects.all()
for row in objs:
print(row.id)
print(row.host)
print(row.port)
print(row.bs.name) 外键,拿到业务线的名字
objs = modesl.serverinfo.objects.all().values("id","host","port","bs__name")
for row in objs:
print(row[‘host‘])
print(row[‘bs__name‘])
demo2 (userinfo 和 bussiness_unit 是多对多关系)
用户表 userinfo
id user pwd email mm(ManyToMany)
业务线表 bussiness_unit
id name
主机表
id host port bs(业务线对象)
用户业务线关系表 *****
id user_id bs_id
obj = models.user.objects.filter(user=‘alex‘).first()
obj.mm.add(1)
obj.mm.add(11)
- 通过用户对象查所负责的所有业务线对象
obj = models.user.objects.filter(user=‘alex‘).first()
queryset = obj.mm.all() 拿到alex负责的所有业务线 -> [业务线对象,业务线对象...]
for row in queryset:
print(row.id)
print(row.name)
- 通过业务线反查对应有哪些人负责? (***反查*** 表名_set)
obj = models.bussiness_unit.objects.filter(name=‘二手车‘).first()
queryset = obj.userinfo_set.all() 拿到负责二手车业务线的用户对象 -> [用户对象,用户对象...]
for row in queryset:
print(row.user)
print(row.pwd)
总结:
1.多对多关系建在哪张表上都可以;
2.如果建在userinfo表上,那么通过用户对象查所负责的bs对象列表就直接用 obj.mm.all()
方便了 userinfo对象,但是bs对象反查userinfo就得用 userinfi_set.all()
==================================================================
今日内容:
1.登录
- 密码加密,对密码进行比较
- 用户登录之后才能访问某些页面
2.cookie是什么?
- 保存在客户端浏览器上的键值对 {k:v}
- cookie依附在请求头或者响应头中
- 浏览器发送请求时会自动携带所访问网站对应的cookie
- 应用
- 实现登录
- 投票
- 每页显示10条/20条...
- 使用
- 设置
response = redirect(‘/index/‘)
response.set_cookie(‘my_cookie‘,md5.encrypt(‘xxx‘))
return response
key,
value=‘‘,
max_age=None, 超时时间:秒数
expires=None, 超时时间:截止日期
path=‘/‘, cookie在哪个url里生效 : 访问指定url时才能读取到cookie, ‘/‘ 表示全部页面都可以
domain=None, 当前域名或者二级域名
secure=False, https
httponly=False
response = redirect(‘/index/‘)
# 设置cookie
response.set_cookie(‘my_cookie‘,md5.encrypt(user))
return response
# 设置cookie过期时间
import datetime
deadline = datetime.datetime.utcnow() + datetime.timedelta(seconds=5)
response.set_cookie(‘my_cookie‘,md5.encrypt(user),expires=deadline)
response.set_cookie(‘my_cookie‘,md5.encrypt(user),max_age=5)
- 获取
ck = request.COOKIES.get(‘my_cookie‘)
# 详细代码如下:
‘‘‘
# models.py
from django.db import models
# Create your models here.
class UserInfo(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
email = models.EmailField(null=True)
‘‘‘
‘‘‘
from django.shortcuts import render,HttpResponse,redirect
from app01 import models
from common import md5
# 判断用户是否登录的装饰器(通过cookie判断)
def auth(func):
def inner(request,*args,**kwargs):
ck = request.COOKIES.get(‘my_cookie‘)
if not ck:
return redirect(‘/login/‘)
return func(request,*args,**kwargs)
return inner
@auth
def index(request):
user = request.COOKIES.get(‘my_cookie‘)
print(request.COOKIES)
# return HttpResponse("登录成功")
return render(request,‘index.html‘,locals())
def login(request):
if "GET" == request.method:
return render(request,‘login.html‘)
else:
user = request.POST.get(‘user‘)
pwd = request.POST.get(‘pwd‘)
obj = models.UserInfo.objects.filter(username=user,password=md5.encrypt(pwd)).first()
if obj:
response = redirect(‘/index/‘)
# 设置cookie过期时间
# import datetime
# deadline = datetime.datetime.utcnow() + datetime.timedelta(seconds=5)
# response.set_cookie(‘my_cookie‘,md5.encrypt(user),expires=deadline)
# response.set_cookie(‘my_cookie‘,md5.encrypt(user),max_age=5)
# 设置cookie
response.set_cookie(‘my_cookie‘,user)
return response
else:
return render(request,‘login.html‘,{‘msg‘:"用户名或密码错误"})
‘‘‘
‘‘‘
# login.html
...
<form action="/login/" method="POST">
{% csrf_token %}
<input type="text" name="user">
<input type="text" name="pwd">
<input type="submit" value="提交"><span style="color: red;">{{ msg }}</span>
</form>
...
# index.html
...
<h1>{{ user }}</h1>
...
‘‘‘
‘‘‘
# md5.py
def encrypt(pwd):
import hashlib
obj = hashlib.md5()
obj.update(pwd.encode(‘utf-8‘))
data = obj.hexdigest()
return data
if __name__ == ‘__main__‘:
print(encrypt(‘123‘))
‘‘‘
3.session
是保存在服务器端的键值对 {k:v}
依赖cookie
Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
更多参考:http://www.cnblogs.com/wupeiqi/articles/5246483.html
生成随机字符串,并将其当做cookie发送给客户端
服务端设置随机字符串作为key,自己设置一些{}:request.session[‘my_session_key‘] = user
- 设置session
request.session[‘yyy‘] = user
return redirect(‘/index/‘)
- 获取session
# 装饰器
def auth(func):
def inner(request,*args,**kwargs):
ck = request.session.get(‘yyy‘)
if not ck:
return redirect(‘/login/‘)
return func(request,*args,**kwargs)
return inner
- 清空session
request.session.clear()
http://www.cnblogs.com/wupeiqi/articles/5246483.html
SESSION_ENGINE = ‘django.contrib.sessions.backends.db‘ # 引擎(默认)
SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)
# 详细代码如下:
‘‘‘
from django.shortcuts import render,HttpResponse,redirect
from app01 import models
from common import md5
# 判断用户是否登录的装饰器(通过session判断)
def auth(func):
def inner(request,*args,**kwargs):
ck = request.session.get(‘my_session_key‘)
if not ck:
return redirect(‘/login/‘)
return func(request,*args,**kwargs)
return inner
@auth
def index(request):
user = request.session.get(‘my_session_key‘)
return render(request,‘index.html‘,locals())
@auth
def order(request):
return render(request,‘order.html‘)
# 登出view
def logout(request):
# 用户登出后清空session
request.session.clear()
return redirect(‘/index/‘)
def login(request):
if "GET" == request.method:
return render(request,‘login.html‘)
else:
user = request.POST.get(‘user‘)
pwd = request.POST.get(‘pwd‘)
obj = models.UserInfo.objects.filter(username=user,password=md5.encrypt(pwd)).first()
if obj:
# 设置session
request.session[‘my_session_key‘] = user
return redirect(‘/index/‘)
else:
return render(request,‘login.html‘,{‘msg‘:"用户名或密码错误"})
‘‘‘
‘‘‘
# urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r‘^admin/‘, admin.site.urls),
url(r‘^login/‘, views.login),
url(r‘^logout/‘, views.logout),
url(r‘^index/‘, views.index),
url(r‘^order/‘, views.order),
]
‘‘‘
‘‘‘
# login.html
...
<form action="/login/" method="POST">
{% csrf_token %}
<input type="text" name="user">
<input type="text" name="pwd">
<input type="submit" value="提交"><span style="color: red;">{{ msg }}</span>
</form>
...
# index.html
...
<h1>{{ user }}</h1>
...
# order.html
...
<body>
<h1>欢迎登录:{{ request.session.my_session_key }}</h1>
<a href="/logout/">注销</a>
</body>
...
‘‘‘
4.csrf 跨站请求伪造
<form action="/login/" method="POST">
{% csrf_token %}
<input type="text" name="user">
<input type="text" name="pwd">
<input type="submit" value="提交"><span style="color: red;">{{ msg }}</span>
</form>
{% csrf_token %} 在浏览器里默认就是一个隐藏的input标签,如下所示:
<form action="/login/" method="POST">
<input type=‘hidden‘ name=‘csrfmiddlewaretoken‘ value=‘T2Ub1TacecIsEsKJvoUvB3xNSwrEGT0NajwGeO6y58mp1IseYVLL3FBnXtOT3WgW‘ />
<input type="text" name="user">
<input type="text" name="pwd">
<input type="submit" value="提交"><span style="color: red;"></span>
</form>
而 {{ csrf_token }} 这个就是这个隐藏标签的value值
跨站请求的漏洞:
<form method="POST" action="http://www.icbc.com.cn/icbc/">
<input type="text" name="from" style="display: none;" value="A的卡号">
<input type="text" name="to" style="display: none;" value="黑客的卡号">
<input type="text" name="money" style="display: none;" value="1000000000">
<input type="submit" name="" value="点我">
</form>
{% csrf_token %}
# 首先不提交 csrf_token 的情况:报错403,CSRF verification failed. Request aborted.
<form id="my_form" action="/login/" method="POST">
<input type="text" name="user">
<input type="email" name="email">
<button onclick="ajaxSubmit()">Ajax提交</button>
</form>
<script src="{% static "js/bootstrap.min.js" %}"></script>
<script>
function ajaxSubmit() {
$.ajax({
url:‘/show/‘,
type:‘POST‘,
data:{
‘user‘:$(‘#my_form input[name="user"]‘).val(),
‘email‘:$(‘#my_form input[name="email"]‘).val()
},
success:function (data) {
console.log(data);
}
})
}
</script>
# 注意一点:
# 如果form表单不写action,则默认提交到当前页面
ajax提交csrf_token的几种方式:
# 方式1
<form id="my_form" action="/show/" method="post">
{% csrf_token %}
<input type="text" name="user">
<input type="email" name="email">
<button onclick="ajaxSubmit()">Ajax提交</button>
</form>
<script src="{% static "js/bootstrap.min.js" %}"></script>
<script>
function ajaxSubmit() {
$.ajax({
url:‘/show/‘,
type:‘POST‘,
data:{
‘user‘:$(‘#my_form input[name="user"]‘).val(),
‘email‘:$(‘#my_form input[name="email"]‘).val(),
‘csrfmiddlewaretoken‘:$(‘input[name="csrfmiddlewaretoken"]‘).val()
},
success:function (data) {
console.log(data)
}
})
}
</script>
# 方式2 只能写在模板里
<body>
<form id="my_form" action="/show/" method="post">
{% csrf_token %}
<input type="text" name="user">
<input type="email" name="email">
<button onclick="ajaxSubmit()">Ajax提交</button>
</form>
<script src="{% static "js/bootstrap.min.js" %}"></script>
<script>
function ajaxSubmit() {
$.ajaxSetup({
data: {‘csrfmiddlewaretoken‘:‘{{ csrf_token }}‘}
});
$.ajax({
url:‘/show/‘,
type:‘POST‘,
data:{
‘user‘:$(‘#my_form input[name="user"]‘).val(),
‘email‘:$(‘#my_form input[name="email"]‘).val()
},
success:function (data) {
{# do something...#}
}
})
}
</script>
</body>
# 后端得到的数据:
类型:<class ‘django.http.request.QueryDict‘>
数据:<QueryDict: {‘csrfmiddlewaretoken‘: [‘raZNrc77aQn7cr5Wr6gtTgOaTdNWZKF0HmAfN6kqlGzmyrr4Dw7DUcSVQ6ZHcFoQ‘], ‘email‘: [‘borui@qq.c
om‘], ‘user‘: [‘borui‘]}>
# 方式3 只能写在模板里
<form id="my_form" action="/show/" method="post">
{% csrf_token %}
<input type="text" name="user">
<input type="email" name="email">
<button onclick="ajaxSubmit()">Ajax提交</button>
</form>
<script src="{% static "js/bootstrap.min.js" %}"></script>
<script>
function ajaxSubmit() {
$.ajax({
url:‘/show/‘,
type:‘POST‘,
data:{
‘user‘:$(‘#my_form input[name="user"]‘).val(),
‘email‘:$(‘#my_form input[name="email"]‘).val(),
‘csrfmiddlewaretoken‘:"{{ csrf_token }}"
},
success:function (data) {
{# do something...#}
}
})
}
</script>
这种方法,循环form表单,把很多input值拿出来组成字典,
然而实际上POST请求最后是需要转换成字符串放到请求体中发给后端的,实际上的字符串如下:
‘csrfmiddlewaretoken=ouyWxV86TJWMttyLwzRkORIcqXjInlDREG9oTPlp4z81PtUTIZIuPNMXnQvtAgmH&user=love&email=love%40qq.com‘
所以,如果ajax里的data字段如果写成一个字典,那么就需要一个转成字符串的过程;
如果直接写成字符串,也是可以的;
$(‘#my_form‘).serialize() 这个方法就可以把form表单里所有的值(包含隐藏的csrf标签)拼接成一个字符串;
# 方法4:
<form id="my_form" action="/show/" method="post">
{% csrf_token %}
<input type="text" name="user">
<input type="email" name="email">
<button onclick="ajaxSubmit()">Ajax提交</button>
</form>
<script src="{% static "js/bootstrap.min.js" %}"></script>
<script>
function ajaxSubmit() {
$.ajax({
url:‘/show/‘,
type:‘POST‘,
data:$(‘#my_form‘).serialize(),
success:function (data) {
console.log(data)
}
})
}
</script>
‘‘‘ 以上4中方法都是把csrf_token放入 请求体 里传递给后端 ‘‘‘
# 方法5 把csrftoken对应的值方到 请求头 里,传递给后端,这样也可以通过csrf验证
首先引入 jquery.cookie.js 插件
然后通过 $.cookie(‘csrftoken‘) 则可以获取到csrftoken对应的值
这种方法,是把csrftoken对应的值放到请求头里,必须按照这个格式:headers:{‘X-CSRFToken‘: $.cookie(‘csrftoken‘)}
这种情况,请求体的内容可以随便写;
<form id="my_form" action="/show/" method="post">
{% csrf_token %}
<input type="text" name="user">
<input type="email" name="email">
<button onclick="ajaxSubmit()">Ajax提交</button>
</form>
<script src="{% static "js/jquery-3.2.1.min.js" %}"></script>
<script src="{% static "js/jquery.cookie.js" %}"></script>
<script src="{% static "js/bootstrap.js" %}"></script>
<script>
function ajaxSubmit() {
$.ajax({
url:‘/show/‘,
type:‘POST‘,
data:{‘k1‘:‘v1‘,‘k2‘:‘v2‘},
headers:{‘X-CSRFToken‘: $.cookie(‘csrftoken‘)},
success:function (data) {
console.log(data)
}
})
}
</script>
总结:
基于ajax提交form表单,发送csrf验证的方式里
最常用的就是 data:$(‘#my_form‘).serialize() 和 headers:{‘X-CSRFToken‘: $.cookie(‘csrftoken‘)}
另外:
关于csrf有两个装饰器:from django.views.decorators.csrf import csrf_exempt,csrf_protect
‘django.middleware.csrf.CsrfViewMiddleware‘,
# 开启则表示全站都使用csrf验证,而csrf_exempt这个装饰器则表示哪些view可以不使用csrf
# 如果不开启,则表示全站都不使用csrf验证,而csrf_protect这个装饰器则表示哪些view可以使用csrf
# 自定义分页模块 request.path_info
标签:www 过期 是什么 reg password encrypt 服务端 data backend
原文地址:http://www.cnblogs.com/standby/p/7508072.html