返回总目录页

Cookie和Session

 

 

原文链接:https://www.cnblogs.com/maple-shaw/articles/9502602.html

cookie 数据解码:https://jwt.io/

 

 

Cookie

首先新建一个项目:

数据库就直接用这个了:

不需要:

我们需要的实现的逻辑是登录之后之后跳转首页

设置登录页面和首页的url

登录页面如下:

1)form表单,post请求方式,是否开启csrf。用户密码输入框添加name属性,如果出错显示渲染信息的地方。以及提交表单的按钮

 登录代码逻辑如下:

1)导入View类,自定义login类继承它。

2)写get和post方法,self是第一个参数,request作为第二个参数,并且接收所有的其它传参

3)get请求时直接返回login的页面

4)post请求时需要获取form表单POST中的username和pwd,并用获取的键值对内容和数据库中用户密码比对,满足相等就重定向页面到首页地址。否则返回登录页面并传用户或密码的error信息渲染到登录页面的提交上面

首页视图函数直接返回字符串:

现在随便输入用户名和密码,提交报错:

输入正确的信息正确跳转到首页

 现在使用两个浏览器登录首页试试都是可以直接/index/地址访问的,而不用用户登录之后才跳转。直接访问地址就可以进入首页

但是正常的逻辑是用户登录成功之后才能跳转到首页。所以我们需要的是登录之后才跳转,没有登录的就让它重新去登录

但是现在有个问题就是,有没有登录是不知道的,对于服务器来说,登录没登录都是一样的。

 

如下:

1)方框是服务器,左圆是浏览器1,右圆是浏览器2
2)浏览器1先是发送一个get请求,获取到登录页面。再发送一个post请求,如果用户名和密码正确那么服务器返回一个重定向地址,然后再get首页页面,服务器返回首页页面
3)浏览器2直接访问index地址,get拿到index页面
4)我们需要实现的是浏览器1这种登录了的可以拿到页面;浏览器2这种没有登录的是不能拿到页面,应该让它登录以后再拿到这个页面,
5)现在的情况是这两种方法都能访问到index页面,这就是http协议无状态做的情况
6)对于浏览器来说,无论谁发来的请求它都不认识,也不会知道你上一次做的事情,下一次请求和上一次请求都是没有关系的,每次请求都是独立的。无论是你发的,别人发的,还是你上次发的请求都是独立的。


7)这样就有一个问题,不记得上一次的操作,也就是不保存你的状态,这就是http是无状态的。这时就要用到cookie来保存我们的状态
8)那么cookie做了什么流程呢?红线是发了post请求,请求过去之后服务器做了一个校验,用户密码登录校验正确之后,返回post请求会在响应数据中多添加了数据并保存在浏览器1中。当浏览器1再次发送请求(橘色的线)时会携带保存的这部分数据。然后服务器再对这部分数据进行校验判断你是登录的用户,然后才让你访问index等需要登录的页面。
9)而浏览器2没有进行登录,也没有服务器在你浏览器上留下的这部分数据,就判断你是未登录用户,然后返回登录页面提示你登录后再访问这个index页面。
10)而这里保存的数据就是cookie。

11)cookie的定义:保存在浏览器本地上一组组键值对
12)cookie的特点:
  1. 由服务器让浏览器进行设置的
  2. 浏览器保存在浏览器本地
  3. 下次访问时自动携带(访问淘宝,携带淘宝给你设置的信息,访问京东,携带京东给你设置的信息)

 

比如博客园,这里就是基于登录做的

 浏览器设置里面找到cookie

关闭cookie:

关闭之后登录的时候那么服务器让浏览器保存cookie,而浏览器设置了不保存,那么我再发送登录进入之后的页面就不再携带这个cookie的信息,就无法登录跳转页面了。博客这里登录会先显示验证通过然后显示红色报错信息。

 

cookie作用是保存信息的,是浏览器上的一组组键值对,登录验证是它的一个应用,而不是专门做登录用的

 cookie还可以这样应用:比如下面这样的页面如果可以设置每页20条数据,那么cookie保存这个数据下次访问还是显示这个数据。保存浏览习惯

cookie投票计数,计数到达次数的浏览器做个限制。应用于简单投票

cookie键值对,GA计数

 

 那么它是如何发送到服务器里面的呢。发送http请求,请求行,请求头,请求体,cookie就保存在请求头当中。多个键值对分号分开。在上面的cookies中将它分开了

两个地方cookie区别;

服务器让浏览器设置,然后浏览器保存在本地,下次访问浏览器的时候自动就携带了这些东西了。

那么服务器端应该在下面设置cookie,也就是登录验证成功重定向操作的时候给你设置一个cookie,

 

 给响应头添加cookie

将csrf的功能注销掉重启服务

这样当我们输入错的时候没有cookie:

当我们form表单填写正确的时候重定向到了首页,在login重定向的时候,显示发送响应cookie让你在浏览器保存了服务端给你设置的键值对

然后重定向访问到index页面,也就是下次访问的时候会自动带上cookie

也就是重定向返回location /index/的时候,就设置了cookie,在HttpResponse响应头中,并将它保存在浏览器中

 当浏览器再次访问的时候就会在请求头中携带保存下来的cookie信息

登录页重定向index页面的时候,get   index页面的视图函数中要获取到cookie进行判断。请求体发送过来的是字符串,在这里封装成字典。想要用它就用字典的方式获取就行了,[]或点get获取

 如果获取的cookie不等于我设置的值那么重定向到登录地址继续登录,否则(cookie验证通过)返回首页内容。

ctrl  shift delete清除浏览数据

再去访问index,跳转到登录:

网页能不能访问是根据状态实现的。把登录状态保存在cookie里面,每次请求来的时候先去获取登录状态。没有状态就让它跳转到登录页面,获取到状态就跳转到访问的页面

如下:新添加一个home页面,这个home页面现在不用登录也能访问

index需要校验,home也需要校验,这时候就要用到装饰器了。

1)在需要登录之后才能访问的页面使用装饰器

 

 

 

 

Cookie的由来

大家都知道HTTP协议是无状态的。

无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况。

一句有意思的话来描述就是人生只如初见,对服务器来说,每次的请求都是全新的。

状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被保留。会话中产生的数据又是我们需要保存的,也就是说要“保持状态”。因此Cookie就是在这样一个场景下诞生。

什么是Cookie

Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。

Cookie的原理

cookie的工作原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能通过Cookie的内容来判断这个是“谁”了。

查看Cookie

我们使用Chrome浏览器,打开开发者工具。


Django中操作Cookie

获取Cookie

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

get_signed_cookie方法的参数:

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

 

设置Cookie

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

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

参数:

  • key, 键
  • value='', 值
  • max_age=None, 超时时间  #如果不加它,默认退出浏览器cookie就失效,需要重新登录;如果给这个参数设置默认值5,那么5秒后cookie失效
  • expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)  #ie浏览器使用的超时时间
  • 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")  # 删除用户浏览器上之前设置的user的cookie值
    return rep

 

访问/logout/,删除了之前在浏览器上设置的值。并将过期时间设置为0

执行删除cookie就是将这两个值一个设置为空,过期时间设置为0

 

 

Cookie版登陆校验

 cookie版登录

浏览器给/login/发了一个post请求,服务器的响应头是Set-Cookie。服务器给浏览器返回的就是Httpresponse对象。我们就是通过这个对象去设置的。
 

 

我们也可以通过这个[]来设置:

设置成功,

将一改成100。本质是客户端给服务端一个请求头,请求头里有cookie,cookie里有键值对。服务器回的话会set-cookie的响应头

三种方法是对响应对象做设置:下面两种方法的本质是[]字典类型方法设置键值对

 

 

Session

 

这两个是文件型数据库的表:

执行命令生成session的表,

又上知应用里面有sessions,

sessions应用里的数据存在下面的表中:

将之前设置cookie的改成设置session,在登录post请求中。之前设置的键值对中值为字符串1,而session可以设置数字1。但是后面访问其它页面时

session设置的是数字1,,后面取的进行判断应该是数字1,下面有误

获取的话可以如下获取:

 

 

 并且session_data会做加密和解密,超时时间也是cookie的超时时间

访问index

超时时间

两周之后cookie会从浏览器清掉,但是session不会从数据库清掉,因为过期了,所以再取取不到了。用下面的方法清除session数据库过期数据

在SQLite数据库中直接修改过期时间会变成时间戳,而mysql中是没有问题的

执行上面的delete方法之后,当前会话对应的cookie还在,但是session表中对应的数据已经被删除了

使用flush

请求发出后响应会将sessionid设置为空,超时时间设置为0。session数据库中的对应记录也被删掉了

并且再次访问sessionid没有了。也就是服务端和客户端都将它删掉了

所以区别:

设置session超时时间:

cookicookie设置10秒

10秒之后cookie不在了但是session表中session还在

过期了的数据要删掉还是要使用:

 

将过期时间设置为0

 过期时间设置为这个了,默认浏览器关闭就失效了

session配置

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Session的由来

Cookie虽然在一定程度上解决了“保持状态”的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是Session。

问题来了,基于HTTP协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的Cookie就起到桥接的作用。

我们可以给每个客户端的Cookie分配一个唯一的id,这样用户在访问时,通过Cookie,服务器就知道来的人是“谁”。然后我们再根据不同的Cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。

总结而言:Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是Cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。

另外,上述所说的Cookie和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失效策略。
复制代码

Session流程解析

Session版登陆验证

def check_login(func):
    @wraps(func)
    def inner(request, *args, **kwargs):
        next_url = request.get_full_path()
        if request.get_signed_cookie("login", salt="SSS", default=None) == "yes":
            # 已经登录的用户...
            return func(request, *args, **kwargs)
        else:
            # 没有登录的用户,跳转刚到登录页面
            return redirect("/login/?next={}".format(next_url))
    return inner


def login(request):
    if request.method == "POST":
        username = request.POST.get("username")
        passwd = request.POST.get("password")
        if username == "xxx" and passwd == "dashabi":
            next_url = request.GET.get("next")
            if next_url and next_url != "/logout/":
                response = redirect(next_url)
            else:
                response = redirect("/class_list/")
            response.set_signed_cookie("login", "yes", salt="SSS")
            return response
    return render(request, "login.html")
session版登录验证

Django中的Session配置

Django中默认支持Session,其内部提供了5种类型的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配置

 

posted @ 2019-06-26 15:27  马昌伟  阅读(267)  评论(0)    收藏  举报
博主链接地址:https://www.cnblogs.com/machangwei-8/