69-django-forms组件源码刨析、cookie与session

今日内容概要

  • forms组件源码html

  • cookie与sessionpython

今日内容详细

forms组件源码

 1 """
 2 切入点:
 3     form_obj.is_valid()
 4 """
 5 def is_valid(self):
 6         """
 7         Returns True if the form has no errors. Otherwise, False. If errors are
 8         being ignored, returns False.
 9         """
10    return self.is_bound and not self.errors
11    # 若是is_valid要返回True的话 那么self.is_bound要为True self.errors要为Flase
12   
13   
14 self.is_bound = data is not None or files is not None  # 只要你传值了确定为True
15 
16 
17 @property
18 def errors(self):
19         "Returns an ErrorDict for the data provided for the form"
20         if self._errors is None:
21             self.full_clean()
22         return self._errors
23 
24 # forms组件全部的功能基本都出自于该方法
25 def full_clean(self):
26       self._clean_fields()  # 校验字段 + 局部钩子
27     self._clean_form()  # 全局钩子
28     self._post_clean() 
29 
30 
31 # 经过看源码获得得第二种添加钩子提示的方式
32  from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
33 
34     def clean_username(self):
35         username = self.cleaned_data.get('username')
36         if '666' in username:
37             # self.add_error('username', '6个粑粑憨逼')
38             raise ValidationError('6个粑粑憨逼')
39         return username
40         

cookie与session

"""
发展史
    1.网站都没有保存用户功能的需求 全部用户访问返回的结果都是同样的
        eg:新闻、博客、文章...
    
    2.出现了一些须要保存用户信息的网站
        eg:淘宝、支付宝、京东...
        
        以登录功能为例:若是不保存用户登录状态 也就意味着用户每次访问网站都须要重复的输入用户名和密码(你以为这样的网站你还想用吗?)
        当用户第一次登录成功以后 将用户的用户名密码返回给用户浏览器 让用户浏览器保存在本地,以后访问网站的时候浏览器自动将保存在浏览器上的用户名和密码发送给服务端,服务端获取以后自动验证
        早起这种方式具备很是大的安全隐患
        
        
        优化:
            当用户登录成功以后,服务端产生一个随机字符串(在服务端保存数据,用kv键值对的形式),交由客户端浏览器保存
            随机字符串1:用户1相关信息
            随机字符串2:用户2相关信息
            随机字符串3:用户3相关信息
            以后访问服务端的时候,都带着该随机字符串,服务端去数据库中比对是否有对应的随机字符串从而获取到对应的用户信息
            
    
  
可是若是你拿到了截获到了该随机字符串,那么你就能够冒充当前用户 其实仍是有安全隐患的


你要知道在web领域没有绝对的安全也没有绝对的不安全
"""
cookie
    服务端保存在客户端浏览器上的信息均可以称之为cookie
  它的表现形式通常都是k:v键值对(能够有多个)
session
    数据是保存在服务端的而且它的表现形式通常也是k:v键值对(能够有多个)
    
    
下述内容暂时了解便可 先给我搞明白最简单的cookie与session使用再说话!
还想了解见:https://www.cnblogs.com/Dominic-Ji/p/10886902.html
token
    session虽然数据是保存在服务端的 可是禁不住数据量大
  服务端再也不保存数据
      登录成功以后 将一段用户信息进行加密处理(加密算法以后你公司开发知道)
    将加密以后的结果拼接在信息后面 总体返回给浏览器保存 
    浏览器下次访问的时候带着该信息 服务端自动切去前面一段信息再次使用本身的加密算法
    跟浏览器尾部的密文进行比对
jwt认证
    三段信息
  (后期会讲 结合django一块儿使用) 
    
总结:
    1.cookie就是保存在客户端浏览器上的信息
    2.session就是保存在服务端上的信息
    3.session是基于cookie工做的(其实大部分的保存用户状态的操做都须要使用到cookie)

cooike

1 '''
2 cookie 是一个很是具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是
3 浏览器实现的一种数据存储功能。
4 
5 cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的
6 文本文件内,下一次请求同一网站时会把该cookie发送给服务器。因为cookie是存在
7 客户端上的,因此浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据
8 太多磁盘空间,因此每一个域的cookie数量是有限的。
9 '''

session

 1 '''
 2 session 从字面上讲,就是会话。这个就相似于你和一我的交谈,你怎么知道当前和
 3 你交谈的是张三而不是李四呢?对方确定有某种特征(长相等)代表他就是张三。
 4 
 5 session 也是相似的道理,服务器要知道当前发请求给本身的是谁。为了作这种区分,
 6 服务器就要给每一个客户端分配不一样的“身份标识”,而后客户端每次向服务器发请求的
 7 时候,都带上这个“身份标识”,服务器就知道这个请求来自于谁了。至于客户端怎么
 8 保存这个“身份标识”,能够有不少种方式,对于浏览器客户端,你们都默认采用 cookie
 9  的方式。
10 
11 服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会
12 被销毁。这种用户信息存储方式相对cookie来讲更安全,但是session有一个缺陷:如
13 果web服务器作了负载均衡,那么下一个操做请求到了另外一台服务器的时候session会
14 丢失。 

Cookie操做

 1 # 虽然cookie是服务端告诉客户端浏览器须要保存内容
 2 # 可是客户端浏览器能够选择拒绝保存 若是禁止了 那么 只要是须要记录用户状态的网站登录功能都没法使用了
 3 
 4 # 视图函数的返回值
 5 return HttpResponse()
 6 return render()
 7 return redirect()
 8 
 9 
10 obj1 = HttpResponse()
11 # 操做cookie
12 return obj1
13 
14 obj2 = render()
15 # 操做cookie
16 return obj2
17 
18 obj3 = redirect()
19 # 操做cookie
20 return obj3
21 # 若是你想要操做cookie,你就不得不利用obj对象
22 
23 
24 """
25 设置cookie
26     obj.set_cookie(key,value)
27 获取cookie
28     request.COOKIES.get(key)
29 在设置cookie的时候能够添加一个超时时间
30     obj.set_cookie('username', 'jason666',max_age=3,expires=3)
31     
32     max_age
33     expires
34         二者都是设置超时时间的 而且都是以秒为单位
35         须要注意的是 针对IE浏览器须要使用expires
36 主动删除cookie(注销功能)
37   request.delete_cookie('username')  
38     
39 """
40 # 咱们完成一个真正的登录功能
41 # 校验用户是否登录的装饰器
42 """
43 用户若是在没有登录的状况下想访问一个须要登录的页面
44 那么先跳转到登录页面 当用户输入正确的用户名和密码以后
45 应该跳转到用户以前想要访问的页面去 而不是直接写死
46 """
47 def login_auth(func):
48     def inner(request,*args,**kwargs):
49         # print(request.path_info)
50         # print(request.get_full_path())  # 可以获取到用户上一次想要访问的url
51         target_url = request.get_full_path()
52         if request.COOKIES.get('username'):
53             return func(request,*args,**kwargs)
54         else:
55             return redirect('/login/?next=%s'%target_url)
56     return inner
57 
58 def login(request):
59     if request.method == 'POST':
60         username = request.POST.get('username')
61         password = request.POST.get('password')
62         if username == 'jason' and password == '123':
63 
64             # 获取用户上一次想要访问的url
65             target_url = request.GET.get('next')  # 这个结果多是None
66             if target_url:
67                 obj = redirect(target_url)
68             else:
69                 # 保存用户登录状态
70                 obj = redirect('/home/')
71             # 让浏览器记录cookie数据
72             obj.set_cookie('username', 'jason666')
73             """
74             浏览器不仅仅会帮你存
75             并且后面每次访问你的时候还会带着它过来
76             """
77             # 跳转到一个须要用户登录以后才能看的页面
78             return obj
79     return render(request,'login.html')
80 
81 
82 @login_auth
83 def home(request):
84     # 获取cookie信息 判断你有没有
85     # if request.COOKIES.get('username') == 'jason666':
86     #     return HttpResponse("我是home页面,只有登录的用户才能进来哟~")
87     # # 没有登录应该跳转到登录页面
88     # return redirect('/login/')
89     return HttpResponse("我是home页面,只有登录的用户才能进来哟~")
90 
91 
92 @login_auth
93 def logout(request):
94     obj = redirect('/app01/login/')
95     obj.delete_cookie('username')
96     return obj
 1 from django.shortcuts import render, HttpResponse, redirect
 2 
 3 # Create your views here.
 4 
 5 from app01 import models
 6 
 7 
 8 def login_auth(func):
 9     def wrapper(request, *args, **kwargs):
10         print(request.path)
11         print(request.path_info)
12         print(request.get_full_path())
13         target_url = request.get_full_path()
14         if request.COOKIES.get('username'):
15             return func(request, *args, **kwargs)
16         else:
17             return redirect('/app01/login/?next=%s'%target_url)
18 
19     return wrapper
20 
21 
22 @login_auth
23 def home(request):
24     return HttpResponse('欢迎来到app01_home页面')
25 
26 
27 def login(request):
28     if request.method == 'POST':
29         username = request.POST.get('username')
30         password = request.POST.get('password')
31         if username == 'jason' and password == '123':
32             print(request.GET.get('next'))
33             target_url = request.GET.get('next')
34             if target_url:
35                 obj = redirect(target_url)
36             else:
37                 obj = redirect('/app01/home/')
38             obj.set_cookie('username', 'jason666')
39             return obj
40         else:
41             return HttpResponse('帐号密码错误')
42     return render(request, 'login.html')
43 
44 
45 @login_auth
46 def logout(request):
47     obj = redirect('/app01/login/')
48     obj.delete_cookie('username')
49     return obj
50 
51 
52 @login_auth
53 def index(request):
54     return HttpResponse('欢迎来到app01_Index页面')
cookie版本登陆认证

cookie其余方法及参数

获取Cookie

request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)


参数:

default: 默认值
salt: 加密盐
max_age: 后台控制过时时间



设置Cookie

rep = HttpResponse(...)
rep = render(request, ...)

rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密盐', max_age=None, ...)



参数:

key, 键
value='', 值
max_age=None, 超时时间
expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
path='/', Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie能够被任何url的页面访问
domain=None, Cookie生效的域名
secure=False, https传输
httponly=False 只能http协议传输,没法被JavaScript获取(不是绝对,底层抓包能够获取到也能够被覆盖)


删除Cookie
def logout(request):
    rep = redirect("/login/")
    rep.delete_cookie("user")  # 删除用户浏览器上以前设置的usercookie值
    return rep

Session操做

 1 """
 2 session数据是保存在服务端的(存?),给客户端返回的是一个随机字符串
 3     sessionid:随机字符串
 4     
 5 1.在默认状况下操做session的时候须要django默认的一张django_session表
 6     数据库迁移命令
 7         django会本身建立不少表    django_session就是其中的一张
 8         
 9 
10 django默认session的过时时间是14天
11     可是你也能够人为的修改它
12     
13 
14 设置session    
15 request.session['key'] = value
16 
17 获取session
18 request.session.get('key')
19 
20 设置过时时间
21 request.session.set_expiry()
22     括号内能够放四种类型的参数
23         1.整数                        多少秒
24         2.日期对象               到指定日期就失效
25         3.0                                一旦当前浏览器窗口关闭马上失效
26         4.不写                        失效时间就取决于django内部全局session默认的失效时间
27 
28 清除session    
29     request.session.delete()  # 只删服务端的 客户端的不删
30     request.session.flush()  # 浏览器和服务端都清空(推荐使用)
31 
32 
33 session是保存在服务端的 可是session的保存位置能够有多种选择
34     1.MySQL
35     2.文件
36     3.redis
37     4.memcache
38     ...
39     
40 
41 django_session表中的数据条数是取决于浏览器的
42     同一个计算机上(IP地址)同一个浏览器只会有一条数据生效
43     (当session过时的时候可能会出现多条数据对应一个浏览器,可是该现象不会持续好久,内部会自动识别过时的数据清除 你也能够经过代码清除)
44     
45     主要是为了节省服务端数据库资源
46 """
47 
48 request.session['hobby'] = 'girl'
49     """
50     内部发送了那些事
51         1.django内部会自动帮你生成一个随机字符串
52         2.django内部自动将随机字符串和对应的数据存储到django_session表中
53             2.1先在内存中产生操做数据的缓存
54             2.2在响应结果django中间件的时候才真正的操做数据库
55         3.将产生的随机字符串返回给客户端浏览器保存
56     """
57 request.session.get('hobby')
58     """
59     内部发送了那些事
60         1.自动从浏览器请求中获取sessionid对应的随机字符串
61         2.拿着该随机字符串去django_session表中查找对应的数据
62         3.
63             若是比对上了 则将对应的数据取出并以字典的形式封装到request.session中
64             若是比对不上 则request.session.get()返回的是None
65     """
66   
67   
68 # 利用session实现登录验证
 1 from django.shortcuts import render, HttpResponse, redirect
 2 
 3 
 4 # Create your views here.
 5 
 6 
 7 def login_auth(func):
 8     def wrapper(request, *args, **kwargs):
 9         target_url = request.get_full_path()
10         if request.session.get('jason'):
11             return func(request, *args, **kwargs)
12         else:
13             return redirect('/app02/login/?next=%s'%target_url)
14 
15     return wrapper
16 
17 
18 def login(request):
19     if request.method == 'POST':
20         username = request.POST.get('username')
21         password = request.POST.get('password')
22         if username == 'jason' and password == '123':
23             target_url = request.GET.get('next')
24             if target_url:
25                 obj = redirect(target_url)
26             else:
27                 obj = redirect('/app02/home/')
28             request.session['jason'] = 'haha6666'
29             request.session.set_expiry(30)
30             return obj
31         else:
32             HttpResponse('帐号或密码错误')
33     return render(request, 'login.html')
34 
35 
36 @login_auth
37 def home(request):
38     return HttpResponse('欢迎来到app_02home页面')
39 
40 
41 @login_auth
42 def index(request):
43     return HttpResponse('欢迎来到app_02index页面')
44 
45 
46 @login_auth
47 def logout(request):
48     request.session.flush()
49     return redirect('/app02/login/')
session版本登陆认证

django中的session方法

# 获取、设置、删除Session中数据
request.session['k1']
request.session.get('k1',None)
request.session['k1'] = 123
request.session.setdefault('k1',123) # 存在则不设置
del request.session['k1']


# 全部 键、值、键值对
request.session.keys()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()

# 会话session的key
request.session.session_key

# 将全部Session失效日期小于当前日期的数据删除
request.session.clear_expired()

# 检查会话session的key在数据库中是否存在
request.session.exists("session_key")

# 删除当前会话的全部Session数据
request.session.delete()
  
# 删除当前的会话数据并删除会话的Cookie。
request.session.flush() 
    这用于确保前面的会话数据不能够再次被用户的浏览器访问
    例如,django.contrib.auth.logout() 函数中就会调用它。

# 设置会话Session和Cookie的超时时间
request.session.set_expiry(value)
    * 若是value是个整数,session会在些秒数后失效。
    * 若是value是个datatime或timedelta,session就会在这个时间后失效。
    * 若是value是0,用户关闭浏览器session就会失效。
    * 若是value是None,session会依赖全局session失效策略。

django中的session配置

1. 数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)

2. 缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也能够是memcache),此处别名依赖缓存的设置

3. 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
SESSION_FILE_PATH = None                                    # 缓存文件路径,若是为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() 

4. 缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎

5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎

其余公用设置项:
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,默认修改以后才保存(默认)
django中的session配置

CBV如何添加装饰器

 1 from django.views import View
 2 from django.utils.decorators import method_decorator
 3 """
 4 CBV中django不建议你直接给类的方法加装饰器
 5 不管该装饰器能都正常给你 都不建议直接加
 6 """
 7 
 8 # @method_decorator(login_auth,name='get')  # 方式2(能够添加多个针对不一样的方法加不一样的装饰器)
 9 # @method_decorator(login_auth,name='post')
10 class MyLogin(View):
11     @method_decorator(login_auth)  # 方式3:它会直接做用于当前类里面的全部的方法
12     def dispatch(self, request, *args, **kwargs):
13         return super().dispatch(request,*args,**kwargs)
14     # @method_decorator(login_auth)  # 方式1:指名道姓
15     def get(self,request):
16         return HttpResponse("get请求")
17 
18     def post(self,request):
19         return HttpResponse('post请求')

今日测验

1 """
2 1.什么是cookie和session,你能描述一下它们的由来和工做机制吗(切勿糊弄,敷衍了事)
3 2.django中如何操做cookie和session,请写出尽可能多的操做方法,并针对session的操做
4 方法详细内部发生的事情,django默认的session失效时间是多久(切勿糊弄,敷衍了事)
5 3.面相对象中的__init__和__new__的区别是什么,利用__new__能够实现什么
6 4.如何给CBV添加装饰器,列举你所知道的几种方式
7 """

今日内容回顾

forms组件源码

 1 #入口:form_obj.is_valid()
 2 
 3 # 校验字段和钩子函数的执行
 4 
 5 # 报错提示 其实能够有两种方式(针对局部钩子函数)
 6   1.self.add_error()
 7   2.raise ValidationError()
 8 
 9 """
10 python源码里面使用最频繁的其实就是反射
11 """
forms组件源码

cookie与session

 1 # cookie与session产生缘由
 2         因为http协议是无状态的
 3 
 4 # cookie概念
 5     服务端设置保存在客户端浏览器上的键值对(只要符合前面的定义均可以叫cookie)
 6     cookie虽然是服务端设置的可是浏览器能够选择不保存
 7   
 8 # session概念
 9     存储在服务端上的键值对(用来标识当前用户)    须要基于cookie才能工做
10   其实大部分的保存状态的实现都须要基于cookie来作
11 
12 # 在web领域没有绝对的安全
13     基本上防护措施都须要程序员本身写代码完善,而且以内完善无法杜绝
cookie与session

django操做cookie

 1 # 须要借助于HttpResponse对象
 2 
 3 # 设置cookie
 4 obj.set_cookie(key,value)  
 5 # 超时时间
 6 obj.set_cookie(key,value,max_age/expires)  
 7     expires  针对IE须要用这个参数              数字是以秒为单位
 8 # 加盐
 9 obj.set_signed_cookie(key,value,salt='')
10 # 获取
11 request.COOKIES.get(key)
12 request.get_signed_cookie(key,salt='')
13 # 删除
14 obj.delete_cookie(key)
15 
16 """
17 校验用户是否登录才能访问视图函数的装饰器
18     可以记录用户在没有登录以前想要访问的页面,登录以后跳转到对应的页面
19     request.path
20     request.path_info
21     request.get_full_path()
22 """
django操做cookie

django操做session

 1 """
 2 1.session是存储在服务端的 django默认状况下是须要借助于django_session表
 3 来存储数据 也就意味着若是你想要操做session那么必须先执行数据库迁移命令让
 4 django先把django_session表建立出来(no such table:django_session)
 5 
 6 2.django默认的session过时时间是14天
 7 
 8 3.session存储在服务端 能够有不少地方存储
 9     1.表
10     2.文件
11     3.缓存
12     4.其余
13     ...
14 """
15 # 设置
16 request.session[key] = value
17     """
18     三件事
19     """
20 # 获取
21 request.session.get(key)
22     """
23     三件事
24     """
25 # 删除
26 request.session.delete()
27 request.session.flush()
28 # 设置超时时间
29 request.session.set_expiry()
30     1.数字                                                            秒数
31   2.datetime/timedelta格式                        日期格式
32   3.None                                                         参加全局失效策略
33   4.0                                                                 窗口关闭即失效
34 
35 """
36 基于session实现用户登录
37 
38 有时候若是多个视图函数都须要使用到一些数据的话,你也能够考虑将该数据存储到django_session表中,方便后续的使用
39     eg:
40         登录验证码(bbs做业会涉及到)
41 """
django操做session

CBV如何添加装饰器

 1 """
 2 django针对CBV添加装饰器须要你导入一个模块
 3 """
 4 from django.utils.decorators import method_decorator
 5 
 6 # 第一种  
 7 class MyCBV(View):
 8   def get(self,request):
 9     return HttpResponse()
10   
11   @method_decorator(login_auth)
12      def post(self,request):
13     return HttpResponse()
14   
15 #  第二种
16 @method_decorator(login_auth,name='post')
17 @method_decorator(index_de,name='get')
18 class MyCBV(View):
19   def get(self,request):
20     return HttpResponse()
21  
22      def post(self,request):
23     return HttpResponse()
24 
25 # 第三种
26 class MyCBV(View):
27   @method_decorator(login_auth)
28   def dispatch(self,request,*args,**kwargs):
29     """
30     看CBV源码能够得出 CBV里面全部的方法在执行以前都须要先通过
31     dispatch方法(该方法你能够当作是一个分发方法)
32     """
33     return super().dispatch(request,*args,**kwargs)
34     
35   def get(self,request):
36     return HttpResponse()
37  
38      def post(self,request):
39     return HttpResponse()
CBV如何添加装饰器

做业

"""
1.整理今日内容到博客
2.利用session实现登录验证
3.复习django阶段所学全部知识点,好好整理回顾(后面没时间了)
4.预习内容:
    https://www.cnblogs.com/Dominic-Ji/p/10881214.html
    
    django中间件
    auth模块
"""
相关文章
相关标签/搜索