首页 > 其他分享 >cookie和session

cookie和session

时间:2022-12-22 22:12:03浏览次数:37  
标签:return 登录 get request session cookie

cookie和session

cookie和session简介

HTTP协议中规定了浏览器不会保存客户端的状态,即无状态的连接特性。这是因为早期的web不需要什么用户注册,看看新闻的功能,所有用户都给一样的界面,不需要什么状态保存。

但随着互联网的发展,我们很多web框架的应用需要保存用户的状态,如最经典的登录状态。

cookie和session是服务端创造出来用于校验的虎符。

  • cookie就是保存在客户端与用户状态相关的信息
  • session就是保存在服务端与用户状态相关的信息

session的工作需要依赖于cookie,而浏览器有权拒绝服务端发送过来的cookie数据

django操作cookie

发送cookie

我们在返回HttpResponse响应对象前,在响应对象COOKIES属性中添加键值对,就可以将cookie保存在客户端的浏览器中了。

# 用户登录
def login_func(request):
    if request.method == 'POST':  # 提交表单打算登录
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'leethon' and password == '123':  # 校验密码成功的话
            obj = redirect('/home/')  # 重定向到比如说首页,但是响应对象不直接return
            obj.set_cookie('name', username)  # return前设置cookie属性,一个name字段保存的用户名
            return obj
    return render(request, 'loginPage.html')  # get请求拿登录界面

检验cookie

浏览器所有cookie在浏览器发送请求时都会携带,并存放在request的COOKIES属性中,我们可以取出校验。

# 访问首页
def home_func(request):
    if request.COOKIES.get('name'):  # 如果COOKIES里面有name,说明有用户登录
    	return HttpResponse('home页面 只有登录的用户才可以查看')  # 用户登录状态下直接访问页面
    return redirect('/login/')  # 用户未登录则跳转到登录界面

登录装饰器综合cookie运用

一个web应用中可能有很多页面都需要登录才能访问,那么这个登录功能我们可以写成装饰器,如果需要就加装,不需要登录则不装。

而且,在访问网页跳转到登录页面时,我们应该让用户登录后可以跳转回原本的页面,也就是obj = redirect('/home/')这一句中的路由不应该写死到返回首页。

要实现上述两个需求就需要编写以下登录功能和装饰器

def login_auth(func):
    def inner(request, *args, **kwargs):  # 视图函数一定含request参数,所以单独先接收便于操作
        target_path = request.path_info  # 拿到请求的路由
        if request.COOKIES.get('name'):  # 校验用户态
            res = func(request, *args, **kwargs)  # 用户登录态则直接返回原本访问的网页
            return res
        return redirect(f'/login/?next={target_path}')  # 将被装饰的视图函数的路由发送给login函数
    return inner

def login(request):
    if request.method == 'POST':  # 提交表单打算登录
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'leethon' and password == '123':  # 校验密码成功的话
            if not request.GET.get('next'):
                obj = redirect('/home/')  # 如果不是通过装饰器重定向来的,就重定向到首页
            else:
	            obj = redirect(f'/{request.GET.get("next")}/')  # 有next就重定向到原本的网页
            obj.set_cookie('name', username)  # 保存登录态
            return obj
    return render(request, 'loginPage.html')  # get请求拿登录界面

@login_auth
def home(request):
    return HttpResponse('home页')

@login_auth
def shop(request):
    return HttpResponse('shop页')

@login_auth
def personal(request):
    return HttpResponse('personal页')

上述代码中,装饰器中的重定向让路由携带了GET请求数据,数据中包含被装饰的视图函数的路由信息;在登录函数中又拿回GET请求数据中的原路由,重定向又返回了用户原本想访问的网页,形成了一套完美的combo。

request有path/path_info/get_full_path()三个有关路由信息的属性

前两种是获得路由(不带?后数据),而get_full_path()方法获得完整路由(携带?后数据)

request.path/path_info:/home/ request.get_full_path():/home/?name=lee

django操作session

在上述cookie的校验中,很明显感觉到只校验COOKIES里面有没有数据显然不严谨,我们应该让用户的cookie与服务端的某个数据再次校验一下,如用户登录时发送了cookie的name存储了用户名,再次访问页面时就让服务端拿到请求时取出cookie的name,比对name是否在我的数据库中。

当然这样也还是不安全,相当于用户知道了用户名就可以通过cookie来访问网页,所以现如今的session,就帮助我们更安全的存储数据。

  • 首先session是存在数据库的表中,django默认执行迁移命令后就会产生一张django_session表存储
  • session默认存储的结构是三个字段,分别是session键、session值和过期时间
  • 校验用户态就是将随机生成的session键交给用户的cookie,将用户信息如用户名存到session值中。当用户再带着cookie过来时,就将cookie的值和表中所有session键比对,如果有对应的session键,就对应的拿到保存着对应用户态的session值。
  • session键和session值都是密文格式。
  • 过期时间expire_data的默认间隔是两周。

设置session

request.session['key'] = value  # value为我想存到session_data字段的值,会自动加密 

底层原理:

  1. 生成一个随机字符串作为session_key存入django_session的session_key字段

  2. 对value数据做加密处理,并在django_session表中存储

    以上两条的随机字符串键和加密value值是一一对应的关系(同属一条记录)

  3. 将随机字符串也发送一份给客户端保存(cookie)

获取session

request.session.get('key')  # 拿到cookie中的session字符串(键key要与设置的相对应)

底层原理:

  1. 获取cookie中的session随机字符串
  2. 去django_session表中根据随机字符串获取加密的数据
  3. 自动解密数据并处理到request.sesion.get()的返回值中

这样我们就可以在存储用户的加密数据在服务端,用户端浏览器cookie只保存一个用于校验的随机字符串,这样就很安全。

设置expire_time间隔

过期时间expire_data的默认间隔是两周,我们也可以自定义这个间隔:

request.session.set_expiry(60)  # 数字单位秒

编写一个session版本的用户登录功能
装饰器、自动记忆跳转、过期时间

class Login(forms.Form):
    username = forms.CharField(max_length=8, min_length=2,
                               # widget=forms.widgets.TextInput(),
                               error_messages={
                                   'max_length': "啊 长了",
                                   'min_length': "啊 短了",
                               }
                               )  # 字符字段,限定最大最小长度
    password = forms.CharField(max_length=16, min_length=6,
                               widget=forms.widgets.PasswordInput(),
                               )

    def clean(self):
        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')
        user_obj = models.User.objects.filter(username=username).first()
        if not user_obj:
            self.add_error('username', '用户名不存在')
        elif not user_obj.password == password:
            self.add_error('password', '密码不正确')
        return self.cleaned_data


def login_auth(func):
    def inner(request, *args, **kwargs):  # 视图函数一定含request参数,所以单独先接收便于操作
        target_path = request.path_info  # 拿到请求的路由
        username = request.session.get('key')  # 拿到登录态
        # username = request.COOKIES.get('name')
        if username:  # 校验用户态
            res = func(request, *args, **kwargs)  # 用户登录态则直接返回原本访问的网页
            return res
        return redirect(f'/login/?next={target_path}')  # 将被装饰的视图函数的路由发送给login函数

    return inner


def login(request):
    login_obj = Login()
    if request.method == 'POST':  # 提交表单打算登录
        login_obj = Login(request.POST)
        if login_obj.is_valid():  # 数据有效且密码校验也正确
            if not request.GET.get('next'):
                obj = redirect('/home/')  # 如果不是通过装饰器重定向来的,就重定向到首页
            else:
                obj = redirect(request.GET.get("next"))  # 有next就重定向到原本的网页
            request.session['key'] = login_obj.cleaned_data.get('username')  # 保存登录态
            # obj.set_cookie('name', username)  # 保存登录态
            return obj
    return render(request, 'loginPage.html', locals())  # get请求拿登录界面


@login_auth
def home(request):
    return HttpResponse('home页')

@login_auth
def home1(request):
    return HttpResponse('home1页')

标签:return,登录,get,request,session,cookie
From: https://www.cnblogs.com/Leethon-lizhilog/p/16999695.html

相关文章

  • django中间键、cookie与session简介、django操作cookie、django操作session
    django中间件如何自定义中间件django中间件三个了解方法基于django中间件的功能设计cookie与session简介django操作cookiecookie实操django操作ses......
  • cookie和session
    内容概要django中间件三个了解的方法基于django中间件实现功能的插拔式设计cookie与session简介django操作cookiedjango操作session内容详细django中间件三个......
  • cookie与seccion
    目录django操作cookiedjango操作cookiedjango操作session设置session获取session补充说明"""回忆:HTTP协议的四大特性 1.基于请求响应 2.基于TCP、IP作用于应用层之上......
  • Django-cookie和session
    1.cookies与session简介1.最早期的互联网不需要保存用户信息,所有用户哪怕之前成功登陆每次用户登录也要重新输入账号和密码。2.cookie:保存在客户端与用户状态相关的数......
  • 12月22日内容总结——django中间件的三个了解要求的方法、基于django中间件的功能设计
    目录一、django中间件三个了解的方法二、django中间件五个方法的执行流程详解三、基于django中间件的功能设计功能设计介绍如何利用字符串导入模块功能模拟四、cookie与ses......
  • django之cookie与session
    目录cookie与session简介django操作cookiedjango操作sessioncookie与session简介"""回忆:HTTP协议四大特性 1.基于请求响应 2.基于TCP、IP作用于应用层之上的协议 3.......
  • django中间件三个了解的方法、 基于django中间件的功能设计、 cookie与session简介、
    目录django中间件三个了解的方法基于django中间件的功能设计cookie与session简介django操作cookiedjango操作cookiedjango操作sessiondjango中间件三个了解的方法1.proc......
  • session实现servlet数据共享
    为了满足老师考试要求,要实现数据共享,要实现顾客登录的功能,登录后进行增删改查要对该顾客进行操作,所以需要将该顾客的一些信息共享给其他操作,找了一些资料,来通过session实现......
  • javaweb总结5-自定义Session
    Session在存储安全性要求较高的会话信息方面是必不可少的,Session当然绝对不是用来存储用户登录状态的,但类似验证码等敏感信息却必须存储在Session中。对于分布式Web应用自......
  • Session的简单应用进行传值
    session可以看做是一个hashmap:存取值的原理同java中的HashMap的键值对相同session.setAttribute("key",value);是session存值的方法,session.getAttribute(key);是sess......