在网站刚刚兴起的时候,很多网站都没有保护用户访问功能的需求,所有用户访问的结果都一样,例如一些新闻、博客、文章等其他网站。后来出现了一些能够保存用户信息的网站,例如:淘宝、支付宝、京东...以登陆功能为例:如果不保存用户登陆状态,也就意味着用户每次访问网站都需要重复的输入用户名和密码(你觉得这样的网站你还想用吗?)。当用户第一次登陆成功之后 将用户的用户名密码返回给用户浏览器 让用户浏览器保存在本地,之后访问网站的时候浏览器自动将保存在浏览器上的用户名和密码发送给服务端,服务端获取之后自动验证,但是这种方式具有非常大的安全隐患。后来对这种方式进行优化,当用户登陆成功之后,服务端产生一个随机字符串(在服务端保存数据,用kv键值对的形式),交由客户端浏览器保存,(随机字符串1:用户1相关信息,随机字符串2:用户2相关信息,随机字符串3:用户3相关信息),之后再访问服务端的时候,都带着该随机字符串,服务端去数据库中比对是否有对应的随机字符串,从而获取到对应的用户信息。但是如果你拿到了截获到了该随机字符串,那么你就可以冒充当前用户 其实还是有安全隐患的,你要知道在web领域没有绝对的安全也没有绝对的不安全。
以上讲的就是网站在保存用户访问信息的一些发展,那么在现如今是如何对用户信息进行保存的呢?
cookie:
服务端保存在客户端浏览器上的信息都可以称之为cookie,它的表现形式一般都是k:v键值对(可以有多个)
session:
数据是保存在服务端的并且它的表现形式一般也是k:v键值对(可以有多个)
token
session虽然数据是保存在服务端的 但是禁不住数据量大,服务端不再保存数据,登陆成功之后 将一段用户信息进行加密处理(加密算法之后你公司开发知道),将加密之后的结果拼接在信息后面 整体返回给浏览器保存 ,浏览器下次访问的时候带着该信息 服务端自动切去前面一段信息再次使用自己的加密算法跟浏览器尾部的密文进行比对。(不要求掌握)
总结:
1.cookie就是保存在客户端浏览器上的信息
2.session就是保存在服务端上的信息
3.session是基于cookie工作的(其实大部分的保存用户状态的操作都需要使用到cookie)
接下来详细介绍cookie和session的具体代码实现
cookie:
初步使用,login页面可以让浏览器记录用户键入的登录信息并且匹配,信息输入正确才能登陆完成。直接进入home页面需要有cookie信息,没有自动跳转到登陆页面。
def login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') #简单的对登录信息进行验证,如果登录信息符合要求,就继续操作 if username == 'fangyu' and password == '1243': #保存用户登陆状态 obj = redirect('/home/') #让浏览器记录cookie数据 obj.set_cookie('username','fangyu1234') return obj return render(request,'login.html') def home(request): #在直接输入本url的时候,会获取用户的cookie信息,判断是否已经的登录 if request.COOKIES.get('username') == 'fangyu1234': return HttpResponse('home页面,登陆成功才能进来') #验证未通过就挑战到登陆页面 return redirect('/login/')
利用装饰器对多个页面提供cookie验证信息
直接键入home页面,如果home页面含有用户登陆得cookie信息,可以直接进行访问,如果不含有,跳转到login页面
def login_auth(func): def inner(request,*args,**kwargs): if request.COOKIES.get('username'): return func(request,*args,**kwargs) else: return redirect('/login/') return inner def login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') #简单的对登录信息进行验证,如果登录信息符合要求,就继续操作 if username == 'fangyu' and password == '1243': #保存用户登陆状态 obj = redirect('/home/') #让浏览器记录cookie数据 obj.set_cookie('username','fangyu1234') return obj return render(request,'login.html') @login_auth def home(request): return HttpResponse('home页面,登陆成功才能进来')
需求:当用户直接键入一个主网址的相关网址之后,直接校验是否含有用户登录信息,如果没有,跳转到登陆页面,并且登陆完成了可以直接进入之前输入的页面。
def login_auth(func): def inner(request,*args,**kwargs): #获取到用户直接键入的目标网址 target_url = request.get_full_path() if request.COOKIES.get('username'): return func(request,*args,**kwargs) else: #如果用户直接键入目标网址得时候没有cookies信息,那么直接跳转到登陆页面,并且登陆页面含有直接键入的网址信息,能够在输入登陆信息之后跳转到想要登陆的页面 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 == 'fangyu' and password == '1243': ## 获取用户上一次想要访问的url target_url = request.GET.get('next') # 这个结果可能是None,当直接输入login的时候就是None if target_url: #保存用户登陆状态,并且跳转到需要登陆的页面 obj = redirect(target_url) else: obj = redirect('/home/') #让浏览器记录cookie数据 obj.set_cookie('username','fangyu1234') return obj return render(request,'login.html') @login_auth def home(request): # #在直接输入本url的时候,会获取用户的cookie信息,判断是否已经的登录 # if request.COOKIES.get('username') == 'fangyu1234': # return HttpResponse('home页面,登陆成功才能进来') # #验证未通过就挑战到登陆页面 # return redirect('/login/') return HttpResponse('home页面,登陆成功才能进来') @login_auth def index(request): return HttpResponse("我是index页面,只有登陆的用户才能进来哟~") @login_auth def func(request): return HttpResponse("我是func页面,只有登陆的用户才能进来哟~")
在设置cookie的时候可以添加一个超时时间obj.set_cookie('username', 'jason666',max_age=3,expires=3) expires针对IE浏览器
注销功能:
先登陆,在登陆完成之后键入login_out登出,直接跳转到login登陆页面。这个时候再继续访问其他子页面发现均需要登陆
def logout(request): obj = redirect('/login/') obj.delete_cookie('username') return obj
session:
先交几个简单的设置session的方法,设置session:request.session['key'] = value 获取session:request.session.get('key')
session数据是保存在服务端的(存?),给客户端返回的是一个随机字符串:sessionid:随机字符串
1.在默认情况下操作session的时候需要django默认的一张django_session表
执行数据库迁移命令,django会自己创建很多表 django_session就是其中的一张。
django默认session的过期时间是14天,但是你也可以人为的修改它
def set_session(request): request.session['hobby'] = 'girl' """ 内部发送了那些事 1.django内部会自动帮你生成一个随机字符串 2.django内部自动将随机字符串和对应的数据存储到django_session表中 2.1先在内存中产生操作数据的缓存 2.2在响应结果django中间件的时候才真正的操作数据库 3.将产生的随机字符串返回给客户端浏览器保存 """ return HttpResponse('嘿嘿嘿') def get_session(request): print(request.session.get('hobby')) """ 内部发送了那些事 1.自动从浏览器请求中获取sessionid对应的随机字符串 2.拿着该随机字符串去django_session表中查找对应的数据 3. 如果比对上了 则将对应的数据取出并以字典的形式封装到request.session中 如果比对不上 则request.session.get()返回的是None """ return HttpResponse('哈哈哈')
设置完session对象之后可以对过期时间进行设置,不设置的话,默认过期时间是14天。
request.session.set_expiry()
括号内可以放四种类型的参数
1. 整数 多少秒
2. 日期对象 到指定日期就失效
3. 0 一旦当前浏览器窗口关闭立刻失效
4. 不写 失效时间就取决于django内部全局session默认的失效时间
request.session.set_expiry()
删除session
request.session.delete() # 只删服务端的 客户端的不删
request.session.flush() # 浏览器和服务端都清空(推荐使用)
def del_session(request): request.session.delete() return HttpResponse('删喽')
session是保存在服务端的 但是session的保存位置可以有多种选择
1.MySQL
2.文件
3.redis
4.memcache
...
补充:CBV如何添加装饰器
CBV是不允许直接按照普通的方式添加装饰器,需要借助from django.utils.decorators import method_decorator模块来添加装饰器,一共有三种方式添加装饰器
方式1:
class MyLogin(View): # @method_decorator(login_auth) # 方式1:指名道姓 def get(self,request): return HttpResponse("get请求") def post(self,request): return HttpResponse('post请求')
方式2:
@method_decorator(login_auth,name='get') # 方式2(可以添加多个针对不同的方法加不同的装饰器) @method_decorator(login_auth,name='post') class MyLogin(View): def get(self,request): return HttpResponse("get请求") def post(self,request): return HttpResponse('post请求')
方式3:
class MyLogin(View): @method_decorator(login_auth) # 方式3:它会直接作用于当前类里面的所有的方法 def dispatch(self, request, *args, **kwargs): return super().dispatch(request,*args,**kwargs) def get(self,request): return HttpResponse("get请求") def post(self,request): return HttpResponse('post请求')