Django11days

发布时间 2023-11-22 17:42:19作者: 拆尼斯、帕丁顿

Cookie和session发展史

cookie补充

django操作 cookie

session

django操作session三种方法

————————————————————————————————————————————————————————————————————————————————————————

cookie,session发展历史

初始版本的Cookie只能存储很少的数据,并且没有强制加密机制,容易被恶意用户篡改或窃取。因此,随着互联网的快速发展,Cookie引起了一系列安全和隐私问题

由于Cookie存在的局限性,Web开发人员开始寻找更安全、可靠的替代方案。1997年,Sun Microsystems提出了基于服务器的会话管理方案,即Session。
Session是在服务器端存储用户会话数据的一种技术。每当用户访问网站时,服务器会为其创建一个唯一的Session标识符(Session ID),并将会话数据存储在服务器上。
Session ID一般通过Cookie或URL参数传递给客户端,用于识别用户的会话状态

什么是Session,cookie

 

session是服务器端的会话技术,用于保存数据在请求间实现数据共享

session是服务器端的会话技术。服务器为每一个浏览器开辟一块内存空间,即session对象。由于session对象是每一个浏览器特有的,所以用户的记录可以存放在session对象中。同时,每一个session对象都对应一个sessionId,服务器把sessionId写到cookie中,再次访问的时候,浏览器把sessionId带过来,找到对应的session对象

 

 

cookie:客户端的会话技术,保存数据在浏览器!

cookie:一个名称和一个值 一些可选属性 cookie存储的数据大小和个数都有限

cookie写入:response.addCookie() 将cookie从服务器 写入到浏览器

cookie获取:request.getCookies()

 

简而言之 

cookie:

  存储形式: K:V键值对

  存储位置: 客户端

  不安全,信息可能会泄露——基于时代发展  更新新得技术

session

  标识符,来表示是当前用户加密出来的数据

  对敏感信息进行加密处理

      存储服务端:

      标识符配上已的 加密串

      把“已”的标识符+字符串全给客户端

        客户端存储格式

          session_id:返回回来的标识符+加密串

token

  三段式加密

----------------------------------------------

  • cookie就是保存在客户端浏览器上的信息
  • session就是保存在服务端上的信息
  • session是基于cookie工作的(其实大部分的保存用户状态的操作都需要使用cookie)

 

 

 

Cookie的作用

  1. 在浏览器中存放数据

  2. 将浏览器中存放的数据携带到服务器

Cookie的应用场景

 

1.记住用户名

当我们在用户名的输入框中输入完用户名后,浏览器记录用户名,下一次再访问登录页面时,用户名自动填充到用户名的输入框.

 

 

2.自动登录(记住用户名和密码)

当用户在淘宝网站登录成功后,浏览器会记录登录成功的用户名和密码,下次再访问该网站时,自动完成登录功能.

以上这些场景都是使用会话cookie实现的,将上次的信息保存到了cookie中,下次直接从cookie中获取数据信息

 

 

3.保存网站的上次访问时间

我们访问网站的时候,通常会看到网站上显示上次访问时间,这些信息就是在用户访问网站的时候保存在cookie中的

 

小结

cookie:客户端会话技术,将数据保存在浏览器。使用cookie保存用户各自的数据

原文链接:https://blog.csdn.net/m0_67559541/article/details/126496893

以登录功能为例:

  如果不保存用户登陆状态,也就意味着用户每次访问王章都有需要重复的输入代码,显然 这对用户来说 体验极差

解决办法 即是

    当用户第一次登陆成功后将其用户名与密码返回给用户浏览器将其数据保存在本地;之后访问网站的时候浏览器自动将保存在本地的用户名和密码发送给服务端,服务端获取之后自动验证,但其含有很大的安全隐患

    优化:

  当用户登录成功之后,服务端产生一个随机字符串(当在服务端保存数据,用K:V键值对的形式)交由客户端浏览器保存

  之后访问服务端的时候,都带着随机字符串,服务端去数据库中对比是否有匹配到的字符串从而获得用户信息;但是如果截获到当前字符串,也是可以冒充登录,所以还是有危险。

    

 

 

 

变形:

obj = HttpResponse()
return obj

obj1 = render()
return obj1

obj2 = redirect()
return obj2

  如果想要操作cookie,必须进行以上变形才可以

 

-----设置 Cookie----------

obj = HttpResponse()
obj.set_cookie(key,value)
return obj

------获取 cookie-------------

request.COOKIES.get(key)

 

---------设置超时时间------------

obj = HttpResponse()
obj.set_cookie(key,value,max_age=5)
# 设置超时时间 5s 到期
return obj

-----------注销 cookie----------

def logout(request,*args,**kwargs)  

obj = HttpResponse()
# 设置超时时间 5s 到期
obj.delete_cookie(key)
return obj

 

下一步想跳转到某个功能时:   

      obj = redirect('/home/')
      obj.delete_cookie(key)
      return obj

 

简单实现

   路由:

    

urlpatterns = [
path('admin/', admin.site.urls),
path('login/', views.login),
path('home/', views.home),
  ]

视图 views:

    

def login(request):    这里可以+  *args,**kwargs 因为不确定接收是什么数据  
  if request.method == 'POST':
    username = request.POST.get('username')
    password = request.POST.get('password')
    if username == "dream" and password == "521":
      # 登陆成功之后,跳转到登陆成功之后才能看到的页面
      return redirect('/home/')
  return render(request, 'login.html')


def home(request):
  return HttpResponse("登陆成功!")

 

前端 html:

  


<form action="" method="post">
  <p>username:<input type="text" name="username" class="form-control"></p>
  <p>password:<input type="password" name="password" class="form-control"></p>
  <input type="submit" class="btn btn-success">
</form>

 

登陆成功之后的跳转页面,不需要登陆也可以直接访问到,只需要给对应的地址即可

解决登陆问题:

  

from django.shortcuts import render, HttpResponse, redirect


# Create your views here.
def login(request):
  if request.method == 'POST':
    username = request.POST.get('username')
    password = request.POST.get('password')
    if username == "dream" and password == "521":
   

↓从这里开始改↓ # 登陆成功之后,保存用户登陆状态
             obj = redirect('/home/')
               # 让浏览器记录cookie
               obj.set_cookie("sign", "1314521")
'''
浏览器不单单只是帮我们保存cookie
而且在后面每次访问的时候都会带着cookie
'''
# 登陆成功之后,跳转到登陆成功之后才能看到的页面
    return obj
return render(request, 'login.html')


def home(request):
    # 读取携带的cookie,cookie正确登陆成功
    if request.COOKIES.get("sign") == "1314521":
      return HttpResponse("登陆成功!")
    # 读取携带的cookie,cookie不正确跳转到登陆页面
    return redirect('/login/')

 

****用户如果没有登录的情况下想访问一个需要登录的页面,那么先跳转到登录页面,当输入正确的用户名和密码之后 再跳转到用户之前想访问的页面去, 而不是写死!!!

迭代-登陆认证装饰器

  def login(request):

    if request.mothd=='POST':

      username=request.POST.get('username')

      password=request.POST.get('password')

      #获取用户上一次想要访问的 url  路由

      #结果可能为空  -- 直接访问 login

      tag_url =request.GET.get('tag.url')

      if tag_url:

        obj=redirect(tag_url)

      else:

        #登录成功之后,保存用户登录状态

        obj.set_cookie('sign,13111')

       """ 浏览器不单单只是帮我们保存cookie
         而且在后面每次访问的时候都会带着cookie
       """
    # 登陆成功之后,跳转到登陆成功之后才能看到的页面
    return obj
  return render(request, 'login.html')

 

#校验用户登录状态的 装饰器

def auth_check(func):

  def inner(request,*args,**kwargs):

    #获取用户上一次想要访问的url

    tag_url =request.get_full_path()

    #读取携带的cookie,cookie正确登录成功

    if request.COOKIES.get("sign") =="13111"

      res= fuc(request,*args,**kwargs)

      return res

    else:

      #读取携带的 cookie, cookie不正确跳转到登录页面

      return redirect(f "/login/?next={tag_url}")

  return inner

@auth_check

def home(request):

  return HttpResponse("home登陆成功!")

@auth_check

def index(request):

  return HttpResponse("index登陆成功")

 

@auth_check

def index(request):

  return HttpResponse("func登陆成功")

 

 

 

以下是一个完整版的 cookie登陆注册:

    

def login(request, *args, **kwargs):
   #next_url = request.get_full_path()
  # print(next_url)    # /login/?next_url=/home/
  if request.method == 'POST':
    username = request.POST.get("username")
    password = request.POST.get("password")
    if username == "dream" and password == "521":
      next_url = request.GET.get('next_url')
      # print(next_url) # /home/
      obj = redirect(next_url)
      obj.set_cookie('sign', 'user')
      return obj
  else:
    return redirect('/login/')
return render(request, 'login.html')


def login_auth(func):
  def inner(request, *args, **kwargs):
    # print(request.path_info) # /home/
    # print(request.get_full_path()) # /home/?username=111
    next_url = request.get_full_path() # /home/
    # print(next_url)# /home/
    sign = request.COOKIES.get('sign')
    if sign and sign == 'user':
      res = func(request, *args, **kwargs)
      return res
    else:
      return redirect(f'/login/?next_url={next_url}')

  return inner


@login_auth
def home(request, *args, **kwargs):
  return HttpResponse("这是home页面")


# def home(request, *args, **kwargs):
#      sign = request.COOKIES.get('sign')
#      if sign and sign == 'user':
#        return HttpResponse("这是home页面")
#      else:
#        return redirect('/login/')

@login_auth
def index(request, *args, **kwargs):
  return HttpResponse("这是index页面")

设置过期时间

obj.set_cookie('sign', 'user', expires=3)
obj.set_cookie('sign', 'user', max_age=3)

刪除cookie

def logout(request, *args, **kwargs):
  obj = redirect('/home/')
  # 设置超时时间 5s 到期
  obj.delete_cookie('sign')
  return obj

 

-----------------Session

设置Session

request.session['key'] = value

获取Session

request.session.get('key')

设置/获取session多个值

  • 给session设置多个值的时候,存在数据库中的数据仍是一条
  • 但是在取session的时候,可以通过request.session对象获取到设置的多组键值对

清空session  

  request.session.delete():   ————只删除客户端的

用于删除当前用户的Session数据,但会保留Session的Key

意味着Session对象本身仍然存在,但其中的数据将被清空

下次访问时,如果Session没有被重新填充,则会得到一个空的Session对象

示例:

  def clear_session(request):

    request.session.delete()

      #其余操作或返回效应

request.session.flush():

服务端和客户端都删除

该方法用于完全删除当前用户的Session,包括Session对象和所有相关数据

下次访问时,将创建一个新的空Session对象

示例:

  def clear_session(request):

    request.session.flush()

      #其余操作

django_sessoin表中的session数据(必须先迁移数据库,生成django_session表)

session只对当次登陆有效

 

django_session表中的数据条取决于浏览器

同一个计算机(IP地址上)同一个浏览器只会有一条数据生效,多个则不然

当session过期的时候,可能会出现多条数据对应一个浏览器

当关闭浏览器,session对象被持久化到硬盘,但是这些数据不会持久存在;会被定时清楚 节省服务器数据库资源

注意:

第一次调用request.getSession()才会创建session对象,不调用则session对象不存在

session对象在创建时,会自动产生sessionId,由服务器通过cookie方式写入到浏览器缓存中,该cookie的name是JSESSIONID

 

session工作原理:

1.第一次请求,通过request.getSesion()创建session对象

2.创建完session对象时,会生成ssionid,保存到cookie中响应给客户端浏览器

3.第二次请求时,客户端浏览器会携带sessionid到服务器,服务器会根据sesionid找到对应的session对象使用

 

Session代码:

  

def login(request, *args, **kwargs):
  # next_url = request.get_full_path()  
  # print(next_url) # /login/?next_url=/home/
    if request.method == 'POST':  
    username = request.POST.get("username")
    password = request.POST.get("password")
    if username == "dream" and password == "521":
      # next_url = request.GET.get('next_url')
      # print(next_url) # /home/
      request.session['sign'] = 'user'
      obj = redirect('/home/')
      # 设置过期时间
      # obj.set_cookie('sign', 'user', expires=3)
      # obj.set_cookie('sign', 'user', max_age=3)
    return obj
  else:
    return redirect('/login/')
 return render(request, 'login.html')


def login_auth(func):
  def inner(request, *args, **kwargs):
    # print(request.path_info) # /home/
    # print(request.get_full_path()) # /home/?username=111
    next_url = request.get_full_path() # /home/
    # print(next_url)# /home/
    sign = request.session.get('sign')
    # print(sign) # user
    if sign and sign == 'user':
      res = func(request, *args, **kwargs)
      return res
    else:
      return redirect(f'/login/?next_url={next_url}')

return inner


@login_auth
def home(request, *args, **kwargs):
  return HttpResponse("这是home页面")

 

Token

 

session虽然数据是保存在服务端的,但是挡不住数据量大
解决办法:服务端不再保存数据
登陆成功之后,将一段信息加密处理(用自己独特的加密方式进行加密)
将加密之后的结果拼接在信息后面,整体返回给浏览器保存
浏览器下次访问的时候带着该信息,服务端自动切取前面的一段信息再次使用自己的加密算法进行加密
然后用这段密文与携带过来的密文进行比对

 

CBV加装饰器的三种方法

from django.utils.decorators import method_decorator
# 方式一:加载视图函数上面
# @method_decorator(login_auth)
def get(self, request, *args, **kwargs):
return HttpResponse("这是home页面")

def post(self):
...

# 方式二:放在类视图上面 (放的装饰器函数,name指定你的视图函数里面的方法)
# @method_decorator(login_auth, name='get')
# @method_decorator(login_auth, name='post')
class UserView(View):

# 方式三 : dispactch 方法加装饰器 : 本视图函数内所有的视图都需要走装饰器
  @method_decorator(login_auth)
  def dispatch(self, request, *args, **kwargs):
    # Try to dispatch to the right method; if a method doesn't exist,
    # defer to the error handler. Also defer to the error handler if the
    # request method isn't on the approved list.
    if request.method.lower() in self.http_method_names:
      handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    else:
      handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)