一.什么是session
session是保存在服务端的键值对,Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
二.FVB中使用装饰器进行session验证
认证装饰器:
1
2
3
4
5
6
7
8
9
10
|
# 登陆验证
def
auth(func):
'''判断是否登录装饰器'''
def
inner(request,
*
args,
*
*
kwargs):
ck
=
request.session.get(
"username"
)
'''如果没有登陆返回到login.html'''
if
not
ck:
return
redirect(
"/login.html"
)
return
func(request,
*
args,
*
*
kwargs)
return
inner
|
在需要认证的函数执行前加上装饰器认证即可,实际中应用如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
def
login(request):
if
request.method
=
=
"GET"
:
return
render(request,
"login.html"
)
else
:
username
=
request.POST.get(
"user"
)
pwd
=
request.POST.get(
"pwd"
)
pwd
=
md5(pwd)
dic
=
{
"flag"
:
False
}
obj
=
User.objects.
filter
(username
=
username, pwd
=
pwd).first()
if
obj:
request.session[
"username"
]
=
username
return
redirect(
"/index.html"
)
else
:
print
(dic)
return
HttpResponse(json.dumps(dic))
@auth
def
index(request):
user
=
request.session.get(
"username"
)
business
=
Business.objects.
all
().values(
"name"
)
host_list
=
Host.objects.
all
().values(
"id"
,
"host"
,
"port"
,
"business__name"
)
username
=
User.objects.
all
().values(
"username"
)
return
render(request,
'index.html'
, {
'host_list'
:host_list,
"business"
:business,
"user"
:user,
"username"
:username})
@auth
def
addhost(request):
business
=
Business.objects.
all
().values(
"name"
)
if
request.method
=
=
"POST"
:
user
=
request.session.get(
"username"
)
host
=
request.POST.get(
"host"
)
port
=
request.POST.get(
"port"
)
select_business
=
request.POST.get(
"business"
)
business_id
=
Business.objects.
filter
(name
=
select_business).values(
"id"
)[
0
]
host
=
Host.objects.create(host
=
host,
port
=
port,
business_id
=
business_id[
"id"
])
# host.business.add(*business)
return
render(request,
"index.html"
)
return
render(request,
"index.html"
, {
"business"
:business})
@auth
def
up_business(request):
if
request.method
=
=
"POST"
:
user
=
request.session.get(
"username"
)
host
=
request.POST.get(
"host"
)
port
=
request.POST.get(
"port"
)
business_name
=
request.POST.get(
"business"
)
username
=
request.POST.get(
"username"
)
print
(host,port,business_name,username)
return
render(request,
"保存成功"
)
|
三.CBV中使用类继承的方式进行session认证
- cbv是 class based view(基于类)
- cbv基于dispatch进行反射,get获取,post提交
- 应用场景:登录认证(继承dispatch,在dispatch里做session验证)
CBV第一种方式继承
1.单继承
扫盲:(继承的时候,一定要清楚self是哪个类实例化出来的对象,下例,self为B实例化的对象,任何属性优先从自己里面找,找不到在去父类里找)
1
2
3
4
5
6
7
8
9
10
11
12
|
class
A(
object
):
def
aaa(
self
):
print
(
'from A'
)
def
bbb(
self
):
self
.aaa()
class
B(A):
def
aaa(
self
):
print
(
'from B'
)
c
=
B()
c.aaa()
|
应用:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
from
django.views
import
View
class
BaseView(View):
def
dispatch(
self
, request,
*
args,
*
*
kwargs):
# 继承父类的dispatch,因为父类里有返回值,所以也要有return
if
request.session.get(
'username'
):
response
=
super
(BaseView,
self
).dispatch(request,
*
args,
*
*
kwargs)
return
response
else
:
return
redirect(
'/login.html'
)
class
IndexView(BaseView):
def
get(
self
, request,
*
args,
*
*
kwargs):
return
HttpResponse(request.session[
'username'
])
|
2.多继承(继承顺序从左到右)
1
2
3
4
5
6
7
8
9
10
11
12
|
class
BaseView(
object
):
def
dispatch(
self
, request,
*
args,
*
*
kwargs):
if
request.session.get(
'username'
):
response
=
super
(BaseView,
self
).dispatch(request,
*
args,
*
*
kwargs)
return
response
else
:
return
redirect(
'/login.html'
)
class
IndexView(BaseView,View):
#先去找BaseView,BaseView中未定义在去找View
def
get(
self
,request,
*
args,
*
*
kwargs):
return
HttpResponse(request.session[
'username'
])
|
CBV第二种方式装饰器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
from
django.utils.decorators
import
method_decorator
def
auth(func):
#定义装饰器
def
inner(request,
*
args,
*
*
kwargs):
if
request.session.get(
'username'
):
obj
=
func(request,
*
args,
*
*
kwargs)
return
obj
else
:
return
redirect(
'/login.html'
)
return
inner
@method_decorator
(auth,name
=
'get'
)
#放在类顶部就需要method_decorator这个装饰器
class
IndexView(View):
@method_decorator
(auth)
#放在dispatch上就相当于全局都需要经过认证
def
dispatch(
self
, request,
*
args,
*
*
kwargs):
if
request.session.get(
'username'
):
response
=
super
(IndexView,
self
).dispatch(request,
*
args,
*
*
kwargs)
return
response
else
:
return
redirect(
'/login.html'
)
@method_decorator
(auth)
def
get(
self
,request,
*
args,
*
*
kwargs):
return
HttpResponse(request.session[
'username'
])
@method_decorator
(csrf_exempt)
# 无效 csrf 放到post函数上的装饰器,是无效的,需要放到dispath上或者类上
def
post(
self
,request,
*
args,
*
*
kwargs):
return
HttpResponse(request.session[
'username'
])
|
四.中间件middleware
如下是django的生命周期
如下为中间件的执行顺序
- 中间件执行时机:请求到来,请求返回时
- 中间件是一个类:
def process_request(self,request):
print('m2.process_request')
def process_response(self,request, response):
print('m2.prcess_response')
return response
- 应用:
- 请求日志
- 用户登录认证
Django根目录新建md文件夹,新建Middleware.py文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
from
django.utils.deprecation
import
MiddlewareMixin
class
M1(MiddlewareMixin):
'''先执行request,然后到url路由,url之后返回到最上方,在执行view,如果出现错误就直接到response上,执行完,到真正到视图,如果有问题就
执行exception,从下至上查找,如果找到exception就直接执行exception的return在走response返回用户
每个中间件中,4个方法不需要都写.
'''
def
process_request(
self
,request):
if
request.path_info
=
=
"/login.html"
:
return
None
user_info
=
request.session.get(
"username"
)
if
not
user_info:
return
redirect(
"/login.html"
)
|
注:新的django版本可能不存在MiddlewareMixin,需要手动写一下这个类进行继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
class
MiddlewareMixin(
object
):
def
__init__(
self
, get_response
=
None
):
self
.get_response
=
get_response
super
(MiddlewareMixin,
self
).__init__()
def
__call__(
self
, request):
response
=
None
if
hasattr
(
self
,
'process_request'
):
response
=
self
.process_request(request)
if
not
response:
response
=
self
.get_response(request)
if
hasattr
(
self
,
'process_response'
):
response
=
self
.process_response(request, response)
return
response
class
M1(MiddlewareMixin):
def
process_request(
self
,request):
if
request.path_info
=
=
"/login.html"
:
return
None
user_info
=
request.session.get(
"username"
)
if
not
user_info:
return
redirect(
"/login.html"
)
|
settings里配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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'
,
'md.Middleware.M1'
,
]
WSGI_APPLICATION
=
'BBS.wsgi.application'
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
=
True
# 是否每次请求都保存Session,默认修改之后才保存(默认)
|