一、cookie与session简介
1、cookie与session的作用
由来:由于HTTP协议是无状态的,每次请求都是一个全新的请求,并不会帮我们保存一些有用的数据,比如用户名密码等,所以我们想要保存用户的信息那么cookie就登场啦。
简单介绍来说就是用来保存与校验用户的信息。当你第一次登录成功之后 服务端给你返回一个随机字符串保存在客户端浏览器上 , 之后该浏览器再次朝服务端发送请求只需要携带该随机字符串,服务端就能够识别当前的用户身份
2、cookie
保存在客户端的浏览器上的键值对
3、session
保存在服务端上的键值对
4、超前时间的概率
cookie的这种只要 登录过就不需要在登陆也是有时间限制的,一旦你超过了这个时间,下次就还需要去重新登录,但是在你有效时间内你只要登录过了,时间是会顺延的。
5、查看cookie
6、浏览器设置cookie
值得注意的是,浏览器一般都是默认会保存cookie的,但是你自己也可以去修改让它不保存cookie,不过不推荐使用,因为一旦你不保存cookie,那么你很多网站连登录都登录不了
二、cookie的操作
1、前戏
之前我们都是直接返回的是HTTP对象的格式,比如:
return HTTPRedponse(...)
return render(...)
return redirect(...)
那么现在问题来了,我们想要操作cookie就不能够直接返回HTTP对象,得做一点变化,让我也能够操作cookie,所以我们需要这么做,这样就可以去点对象中的一些属性和方法
obj = HTTPRedponse(...)
return obj
obj1 = render(...)
return obj1
obj2 = redirect(...)
return obj2
2、设置cookie
obj.set_cookie()
参数:
- 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获取(不是绝对,底层抓包可以获取到也可以被覆盖)
3、获取cookie
request.COOKIES.get()
4、删除cookie
obj.delete_cookie()
5、path_info与get_full_path
6、装饰器模板
# 装饰器模板 from functools import wraps def login_auth(func): @wraps(func) def inner(request, *args, **kwargs): # print('request.path_info', request.path_info) # print('request.get_full_path():', request.get_full_path()) # 执行被装饰函数之前可以做的事情 target_url = request.path_info # 这个是用户在登录之前想要访问的url if request.COOKIES.get('username'): res = func(request, *args, **kwargs) return res else: return redirect('/login/?next=%s'%target_url) return inner
7、登录函数
def login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') if username == 'yafeng' and password == '123': # 方式一: # target_url = request.GET.get('next','/home/') # 获取用户想要访问的url,有登录之后就给他返回想要访问的,没有就给它返回首页 # 方式二: target_url = request.GET.get('next') # 获取用户想要访问的url,有登录之后就给他返回想要访问的,没有就给它返回首页 # 判断用户登录之前是否有想要访问的url if target_url: # 保存用户登录状态 obj = redirect(target_url) else: obj = redirect('/home/') #设置cookie obj.set_cookie('username', 'yafeng', max_age=3) # max_age=3这是设置超时时间 return obj return render(request, 'login.html')
"""day56 URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.11/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^register/', views.register), url(r'^reg/', views.reg), url(r'^login/', views.login), url(r'^home/', views.home), url(r'^index/', views.index), url(r'^demo/', views.demo), url(r'^logout/', views.logout), ]
from django.shortcuts import render, HttpResponse, redirect, reverse # Create your views here. def register(request): error_dict = {'username': '', 'password': ''} if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') if '金瓶mei' in username: # 提示报错信息 error_dict['username'] = '不符合社会主义核心价值观' if not password: # 提示报错信息 error_dict['password'] = '密码不能为空, 你个DSB' return render(request, 'register.html', locals()) from django import forms # 写之前需要先导入一个模块 from django.forms import widgets # forms之校验数据 class MyRegForm(forms.Form): username = forms.CharField(max_length=8, min_length=3, label='用户名', error_messages={ 'max_length': '用户名最长8位', 'min_length': '用户名最短三位', 'required': '用户名不能为空' }, required=False, initial='reba', widget=forms.widgets.TextInput(attrs={'class': 'form-control c1 c2'}), ) # 限制你的用户名最大为8位数,最小为3位数 password = forms.CharField(max_length=8, min_length=3, label='密码', # widget=forms.widgets.PasswordInput ) confirm_password = forms.CharField(max_length=8, min_length=3, label='确认密码') email = forms.EmailField(label='邮箱',error_messages={ 'required': '邮箱必填', 'invalid': '邮箱格式不正确', }) # 限制必须为符合邮箱类型的数据 # 使用正则去校验 from django.core.validators import RegexValidator # 一看到re就大多数和正则相关 phone = forms.CharField( validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头') ] ) # 全局钩子 def clean(self): # 全局钩子固定叫clean # 校验密码和确认密码是否一致 password = self.cleaned_data.get('password') # self 指代的是当前类产生的对象 confirm_password = self.cleaned_data.get('confirm_password') if not password == confirm_password: # 展示提示信息 self.add_error('confirm_password', '两次密码不一致') # 你想展示到那个字段后面就放那个字段就可以啦 return self.cleaned_data # 局部钩子 def clean_username(self): username = self.cleaned_data.get('username') if '666' in username: self.add_error('username', '光喊666 是不行的') return username # 注意:你把什么勾出来了你就得把什么还回去 # forms渲染页面 def reg(request): # 1、先生成一个空的类的对象 form_obj = MyRegForm() if request.method == 'POST': # 3、获取用户数据并交给forms组件检验 request.POST form_obj = MyRegForm(request.POST) # 4、获取检验结果 if form_obj.is_valid(): return HttpResponse('数据没问题') else: # 获取检验失败的字段和提示信息 print(form_obj.errors) # 2、直接将该对象传给前端页面 return render(request, 'reg.html', locals()) # 装饰器模板 from functools import wraps def login_auth(func): @wraps(func) def inner(request, *args, **kwargs): # print('request.path_info', request.path_info) # print('request.get_full_path():', request.get_full_path()) # 执行被装饰函数之前可以做的事情 target_url = request.path_info # 这个是用户在登录之前想要访问的url if request.COOKIES.get('username'): res = func(request, *args, **kwargs) return res else: 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 == 'yafeng' and password == '123': # 方式一: # target_url = request.GET.get('next','/home/') # 获取用户想要访问的url,有登录之后就给他返回想要访问的,没有就给它返回首页 # 方式二: target_url = request.GET.get('next') # 获取用户想要访问的url,有登录之后就给他返回想要访问的,没有就给它返回首页 # 判断用户登录之前是否有想要访问的url if target_url: # 保存用户登录状态 obj = redirect(target_url) else: obj = redirect('/home/') #设置cookie obj.set_cookie('username', 'yafeng', max_age=3) # max_age=3这是设置超时时间 return obj return render(request, 'login.html') @login_auth def home(request): # 校验浏览器是否有对应的cookie # if request.COOKIES.get('username'): # print(request.COOKIES) # return HttpResponse('我是home页面 只有登录成功的用户才能够访问') # else: # return redirect('/login/') return HttpResponse('我是home页面 只有登录成功的用户才能够访问') @login_auth def index(request): return HttpResponse('我是index页面 只有登录之后的用户才能查看') @login_auth def demo(request): return HttpResponse('我是demo页面 只有登录之后的用户才能查看') @login_auth def logout(request): obj = HttpResponse('注销啦') obj.delete_cookie('username') return obj
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <form action="" method="post"> <p>username:<input type="text" name="username"></p> <p>password:<input type="text" name="password"></p> <input type="submit"> </form> </body> </html>
三、session的操作
1、设置
request.session['key'] = value
你这样书写之后设置发生的事:
1、django内部会自动生成一个随机字符串
2、去django_session表中存储数据 键就是随机字符串 值就是要保存到数据(这件事是中间件干的事)
3、将生成好的随机字符串返回给客户端浏览器 浏览器保存键值对 键就是sessionid 值就是 随机字符串
2、获取
request.session.get('key')
获取时发生的事:
1、djagno会自动去浏览器中的session查找sessionid键值对 获取随机字符串
2、拿着该随机字符串去django_session表中比对数据
3、如果比对上了就将随机字符串对应的数据获取出来并封装到request.session中供用户调用
3、django中session默认的超时时间(14天)
4、设置session和的超时时间
request.session.set_expiry(value)
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta(时间差),session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。
5、删除session
a、删除当前会话的所有session数据
request.session.delete()
b、删除当前的会话数据并删除会话的cookie
request.sesion.flush() 推荐使用这种,删的比较彻底
这是用于确保前面的数据会话数据不可以再次被用户的浏览器访问
def del_session(request): request.session.flush() return HttpResponse('注销啦')
6、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相关设置
7、django_session中的数据
每次看起来都是只有一条是因为同一个浏览器只会被当做一个数据记录到数据表中去,django_session表你还可以把它当做一个临时的存储数据的小仓库,并不一定只能存储与用户相关的数据。