COOKIE 与 SESSION
概念
cookie的使用,不止局限于我们所使用的登录认证,cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生。
cookie的工作原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是“谁”了。
cookie虽然在一定程度上解决了“保持状态”的需求,但是由于cookie本身最大支持4096字节,以及cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是session。session相比于cookie更高效的地方就在于,他不仅局限于cookie将保持状态的信息保存在用户的浏览器本地,而是下派给用户一个随机字符串,然后保存在服务器的存储里面,下次用户带着这个字符串来访问服务器,就可以判断是否可以将保持状态的功能开放给用户。
问题来了,基于http协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的cookie就起到桥接的作用。
我们可以给每个客户端的cookie分配一个唯一的id,这样用户在访问时,通过cookie,服务器就知道来的人是“谁”。然后我们再根据不同的cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。
总结而言:cookie弥补了http无状态的不足,让服务器知道来的人是“谁”;但是cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过cookie识别不同的用户,对应的在session里保存私密的信息以及超过4096字节的文本。
另外,上述所说的cookie和session其实是共通性的东西,不限于语言和框架。
登陆应用
像上述概念中所说的,登录中的应用,如果是使用cookie的话,将会在用户本地保存用户的登录信息,然后保存一个键值对由服务器来判断这个键值对是否存在或者值是否正确,以此来保存登录状态,但是由于登录状态信息都是保存在用户本地浏览器信息内的,所以会有一定的几率被拦截盗取。
session的话则是生成一个随机字符串分发给用户,在自己服务端保存这个字符串,下次用户带着这个字符串就如同门票一样,服务端判断正确后就可以放行,保存登录状态。
当然cookie因为数据是存储在用户的客户端的,所以访问速度要快,session将数据存在服务端,同样的访问的请求也会相对慢。各有优缺点。
Django实现的COOKIE
1、获取Cookie
request.COOKIES['key'] request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None) #参数: default: 默认值 salt: 加密盐 max_age: 后台控制过期时间
2、设置Cookie
rep = HttpResponse(...) 或 rep = render(request, ...) 或 rep = redirect() rep.set_cookie(key,value,...) rep.set_signed_cookie(key,value,salt='加密盐',...)
参数:
''' def set_cookie(self, key, 键 value='', 值 max_age=None, 超长时间 expires=None, 超长时间 path='/', Cookie生效的路径, 浏览器只会把cookie回传给带有该路径的页面,这样可以避免将 cookie传给站点中的其他的应用。 / 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问 domain=None, Cookie生效的域名 你可用这个参数来构造一个跨站cookie。 如, domain=".example.com" 所构造的cookie对下面这些站点都是可读的: www.example.com 、 www2.example.com 和an.other.sub.domain.example.com 。 如果该参数设置为 None ,cookie只能由设置它的站点读取。 secure=False, 如果设置为 True ,浏览器将通过HTTPS来回传cookie。 httponly=False 只能http协议传输,无法被JavaScript获取 (不是绝对,底层抓包可以获取到也可以被覆盖) ): pass '''
由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。
<script src='/static/js/jquery.cookie.js'> </script> $.cookie("key", value,{ path: '/' });
3 删除cookie
response.delete_cookie("cookie_key",path="/",domain=name)
Django实现的SESSION
1、 基本操作
常用:
1、设置Sessions值 request.session['session_name'] ="admin" 2、获取Sessions值 session_name = request.session["session_name"] 3、删除Sessions值 del request.session["session_name"] 4、检测是否操作session值 if "session_name" is request.session :
另:
5、get(key, default=None) fav_color = request.session.get('fav_color', 'red') 6、pop(key) fav_color = request.session.pop('fav_color') 7、keys() 8、items() 9、setdefault() 10、flush() 删除当前的会话数据并删除会话的Cookie。 这用于确保前面的会话数据不可以再次被用户的浏览器访问 例如,django.contrib.auth.logout() 函数中就会调用它。 11 用户session的随机字符串 request.session.session_key # 将所有Session失效日期小于当前日期的数据删除 request.session.clear_expired() # 检查 用户session的随机字符串 在数据库中是否 request.session.exists("session_key") # 删除当前用户的所有Session数据 request.session.delete("session_key") request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。
2、 流程解析
如概念介绍中所说,用户登录后,会生成一个{key:value}形式的键值对,然后自动生成一个随机字符串成为键值对中的key,存到浏览器的cookie中去,每个cookie都有自己相应的随机生成的字符串作为key,value存储的可以是用户信息user,下次当用户再次发起浏览请求时,session字典中的key就会起到唯一标识进行认证的作用。
3、 示例
views:
1 from django.shortcuts import render,HttpResponse,redirect 2 from paging.paging import Pagation #导入自己写的分页组件 3 import json 4 # Create your views here. 5 li=[] 6 for i in range(1,303): 7 temp={"id":i,"name":"alex%s"%i} 8 li.append(temp) 9 def page(request): 10 user=request.session.get("username") 11 if not user: 12 return redirect("/zuoye/") 13 d_page=int(request.GET.get("name",1)) 14 obj=Pagation(d_page,10,11,len(li),request.path_info) #分别要传的值(当前页,每一页放多少数据,每一页放多少个跳转按钮,数据的长度,当前的url) 15 16 lip = li[obj.start:obj.end] #直接引用strat和end方法获取每一页数据的头和尾 17 page_fen=obj.huobiao() #huobiao方法获取底下该出来的跳转分页码 18 return render(request, "class.html", {"list": lip, "page_fen": page_fen, "user": user}) 19 20 def logout(request): 21 # 获取当前用户的随机字符串 22 # 在数据库中将当前数据删除 23 request.session.delete() 24 25 # del request.session['username'] 26 27 return redirect('/zuoye/') 28 29 def login(request): 30 if request.method=="POST": 31 usname=request.POST.get("username") 32 print(usname) 33 pwd=request.POST.get("password") 34 ms = {"name": None,"error_msg":None } 35 if usname=="gaoshengyue"and pwd=="gsy121994": 36 request.session["username"]=usname 37 ms ={"name": usname, "error_msg": None} 38 msg=json.dumps(ms) 39 else: 40 ms = {"name": None, "error_msg": '输入错误'} 41 msg=json.dumps(ms) 42 return HttpResponse(msg) 43 return render(request,"zuoye.html")
template:
1 <!DOCTYPE html> 2 <html lang="zh-CN"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> 7 <title>Title</title> 8 <link rel="stylesheet" href="/static/dist/css/bootstrap.min.css"> 9 <script src="/static/dist/js/bootstrap.min.js"></script> 10 <script src="/static/jquery-3.2.1.min.js"></script> 11 </head> 12 <body> 13 <div class="container"> 14 <h5>欢迎登录:<span>{{ user }}</span><a href="/logout/" style="color: red;">注销</a></h5> 15 <table class="table table-bordered"> 16 <thead> 17 <tr> 18 <th>id</th> 19 <th>姓名</th> 20 </tr> 21 </thead> 22 <tbody> 23 24 {% for item in list %} 25 <tr> 26 <td>{{ item.id }}</td> 27 <td>{{ item.name }}</td> 28 </tr> 29 {% endfor %} 30 31 </tbody> 32 33 </table> 34 <div style="text-align: center"> 35 <ul class="pagination"> 36 {% for item in page_fen %} 37 {{ item|safe }} 38 {% endfor %} 39 40 </ul> 41 </div> 42 </div> 43 </body> 44 </html>
4、session存储的相关配置
(1)数据库配置(默认):
Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。 a. 配置 settings.py 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,默认修改之后才保存(默认)
(2)缓存配置
a. 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎 SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置 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,默认修改之后才保存
(3)文件配置
a. 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎 SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() 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,默认修改之后才保存
用户认证
auth模块
from django.contrib import auth
django.contrib.auth中提供了许多方法,这里主要介绍其中的三个:
1 、authenticate()
提供了用户认证,即验证用户名以及密码是否正确,一般需要username password两个关键字参数
如果认证信息有效,会返回一个 User 对象。authenticate()会在User 对象上设置一个属性标识那种认证后端认证了该用户,且该信息在后面的登录过程中是需要的。当我们试图登陆一个从数据库中直接取出来不经过authenticate()的User对象会报错的!!
user = authenticate(username='someone',password='somepassword')
2 、login(HttpRequest, user)
该函数接受一个HttpRequest对象,以及一个认证了的User对象
此函数使用django的session框架给某个已认证的用户附加上session id等信息。
from django.contrib.auth import authenticate, login def my_view(request): username = request.POST['username'] password = request.POST['password'] user = authenticate(username=username, password=password) if user is not None: login(request, user) # Redirect to a success page. ... else: # Return an 'invalid login' error message. ...
3 、logout(request) 注销用户
from django.contrib.auth import logout def logout_view(request): logout(request) # Redirect to a success page.
该函数接受一个HttpRequest对象,无返回值。当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。
4 、user对象的 is_authenticated()
要求:
1 用户登陆后才能访问某些页面,
2 如果用户没有登录就访问该页面的话直接跳到登录页面
3 用户在跳转的登陆界面中完成登陆后,自动访问跳转到之前访问的地址
方法1:
def my_view(request): if not request.user.is_authenticated(): return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
方法2:
django已经为我们设计好了一个用于此种情况的装饰器:login_requierd()
from django.contrib.auth.decorators import login_required @login_required def my_view(request): ...
若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' (这个值可以在settings文件中通过LOGIN_URL进行修改)。并传递 当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。
User对象
User 对象属性:username, password(必填项)password用哈希算法保存到数据库
is_staff : 用户是否拥有网站的管理权限.
is_active : 是否允许用户登录, 设置为``False``,可以不用删除用户来禁止 用户登录
2.1 、is_authenticated()
如果是真正的 User 对象,返回值恒为 True 。 用于检查用户是否已经通过了认证。
通过认证并不意味着用户拥有任何权限,甚至也不检查该用户是否处于激活状态,这只是表明用户成功的通过了认证。
这个方法很重要,
在后台用request.user.is_authenticated()判断用户是否已经登录,如果true则可以向前台展示request.user.name
2.2 、创建用户
使用 create_user 辅助函数创建用户:
from django.contrib.auth.models import User user = User.objects.create_user(username='',password='',email='')
2.3 、check_password(passwd)
用户需要修改密码的时候 首先要让他输入原来的密码 ,如果给定的字符串通过了密码检查,返回 True
2.4 、修改密码
使用 set_password() 来修改密码
user = User.objects.get(username='') user.set_password(password='') user.save
2.5 、简单示例
注册:
1 def sign_up(request): 2 3 state = None 4 if request.method == 'POST': 5 6 password = request.POST.get('password', '') 7 repeat_password = request.POST.get('repeat_password', '') 8 email=request.POST.get('email', '') 9 username = request.POST.get('username', '') 10 if User.objects.filter(username=username): 11 state = 'user_exist' 12 else: 13 new_user = User.objects.create_user(username=username, password=password,email=email) 14 new_user.save() 15 16 return redirect('/book/') 17 content = { 18 'state': state, 19 'user': None, 20 } 21 return render(request, 'sign_up.html', content)
修改密码:
1 @login_required 2 def set_password(request): 3 user = request.user 4 state = None 5 if request.method == 'POST': 6 old_password = request.POST.get('old_password', '') 7 new_password = request.POST.get('new_password', '') 8 repeat_password = request.POST.get('repeat_password', '') 9 if user.check_password(old_password): 10 if not new_password: 11 state = 'empty' 12 elif new_password != repeat_password: 13 state = 'repeat_error' 14 else: 15 user.set_password(new_password) 16 user.save() 17 return redirect("/log_in/") 18 else: 19 state = 'password_error' 20 content = { 21 'user': user, 22 'state': state, 23 } 24 return render(request, 'set_password.html', content)
写实例在个人百度云~~~~~